Fork me on GitHub

hey all, I'm slowing building/learning my first om/untangled app, and now I came to forms... BTW, is there some good example of multi-field form out there that I could study? TODO mvc app just exposes single text field stuff...


meaning, I need some example of few form fields, and submit button etc...


Is om next kanban app good example of this, or Untangled offers some enhancements in this regard?


untangled doesn’t have any field-specific enhancements, no. we do have the toggle!, set-integer!, and set-string! functions in untangled.client.mutations which are intended to be used for setting ui namespaced keywords on components. Those can definitely be used for form fields. If you’re looking to persist those to the server though, you’ll have to write your own mutations to send that data across the wire. As for good examples of form fields, we don’t have one in Untangled for now. Our apps all use optimistic updates that are immediately pushed to the server, so we have less of a need for more traditional submit logic. I’m periodically working on a cookbook of common code snippets so I can add it to my list — although PRs are always welcome if you find a dev pattern for form fields that you think works well


Is there an easy way to inject an error-handler into the untangled client? When we fail to authenticate we send back 403 and when we fail to authorize we send back 401.


@brianosaurus: yes, you have 2 options. The preferred way is to implement a tx/fallback mutation to handle the errors, then you get to take advantage of the built-in networking. The other option is to implement your own networking object that defines its own error callback.


@ethangracer: Still not exactly clear about purpose of :ui/ attributes. For example, if I have standard text field, should I set onChange handler to call:

(ucm/set-string! this :ui/my-text-field-value :event evt)
or I'm missing the intended purpose here?


or should I just call standard Om's om/update-state! to set component's local state?


@ethangracer: it appears a (defmethod m/mutate 'tx/fallback [env _ {:keys [action execute] :as params}] doesn’t get called.


@vmarcinko The only special thing about ui attributes is that they don't get sent to the server. So depending on what you're trying to do you might use UI attributes or you might use component local state


m is our namespace for untangled.client.mutations


There is no use of tx/fallback in our code yes. You have to implement it for the transaction that you're doing... Not completely clear on how those work, that'd be a question for @tony.kay


@ethangracer: ahhh, gotcha. Thanks again.


@brianosaurus: They are not tested quite enough, and were missing "clear the send queue"; however, in concept they are simple: Include a (tx/fallback { :action mutation-symbol }) in your transact. If the main bits of the transaction fail, the fallback mutations are run (in order)


(transact! '[(my/f) (tx/fallback { :action undo-f })])


the fallbacks never go to the server...they are stored with the tracking of the outgoing network request


additional parameters can be sent to the mutation by including them in the fallback parameter map


@tony.kay: I see. Thanks. IMHO it would be nice to simply add a global error handler in something like new-untangled-client (eventually).


Yeah, that is probably true...the context is often important, though...e.g. what did you do?


The unhappy path definitely needs a bit more work


I suppose you’d need to pass in the http code, what you were up to, etc...


well, the reasoning is as follows: - You did an abstract mutation, which included optimistic updates - The transaction failed on the server (for whatever reason...mutations do return error codes, but it typically isn't useful data) So, you're going to need to do one or more of the following: - Fix your local state (from the optimistic change) can close over that in your original parameters to the fallback - Figure out what the server actually knows. If you are still connected, you can ask (app/load), if you're not, you just don't the UI should probably block and reload when available to restore state


So, say you just added an item to the todo list. Your fallback is to either: remove the todo item, OR reload the entire list


either mutation implies an idea of what the individual transaction was trying to do


It is true that you might be able to detect the exact nature of the error (permission denied) and just undo the add locally


So, that is where we should probably hook the real result (and http code) of the mutation into the fallback handling mutation


For simple/lame apps, a global handler is believable: got an error: reload the whole shebang....but I'd hate to see a monster of spaghetti of case logic in a global handler trying to do something more clever


The point is to have simple reasoning...nothing simpler than reasoning about failures where/when they occur


In the case of a 401 or 403 it makes sense to have a global handler. One is unauthenticated (your login timed out) another is unauthorized (someone revoked your right to do something)


Yep. agreed


@tony.kay: Just wondering. On an optimistic mutation is the old app state passed back to tx/fallback on db failure?


nope, but you can add what you need as parameters to the original fallback call


Hi fellas, I'm using the load-field and lazily-loaded functions like so.


Does DataItem have to have an ident?


Say instead I had a DatatItemsTable component instead that I wanted to pass the entire collection of data items to.


Right now I've got a hack were I use DataItem in the query (of that parent that calls load-field) but use DataItemsTable to render the collection.


I'm not sure if this is frowned upon.