untangled

NEW CHANNEL: #fulcro
2016-10-06T19:01:37.001881Z

if I have a mutation 'create-object what's the pattern for transacting 'show-object IFF 'create-object succeeds in creating the object? should I have a post-mutation for 'create-object and transact! 'show-object in the post mutation?

tony.kay 2016-10-06T19:02:10.001883Z

I take it show-object is a server query?

2016-10-06T19:02:28.001884Z

'show-object changes the :current-tab to show the object, and does load-field-action

tony.kay 2016-10-06T19:02:40.001885Z

put that all in create-object

2016-10-06T19:02:57.001887Z

create-object also hits server though, so it's on server response that tab changes

tony.kay 2016-10-06T19:03:20.001888Z

so, if the server denies something, you can throw an error that will trigger a fallback

tony.kay 2016-10-06T19:03:35.001889Z

I assume create-object might fail from server permissions?

2016-10-06T19:03:43.001890Z

ok (transact! [(create-object) (show-object) (tx/fallback)]) ?

tony.kay 2016-10-06T19:03:50.001891Z

tons of ways to do it. Your example is a bit vague

2016-10-06T19:03:51.001892Z

show-object is only transacted in non-exceptional case

tony.kay 2016-10-06T19:04:08.001894Z

no

2016-10-06T19:04:27.001895Z

yes create-object may fail for various reasons

tony.kay 2016-10-06T19:04:29.001896Z

well, sort of

tony.kay 2016-10-06T19:04:41.001898Z

so here's the thing. A single transaction in UI will be sent as single net transaction

tony.kay 2016-10-06T19:04:57.001899Z

so, yes, if you implement it on the server to abort at create-object, then show-object should not happen

tony.kay 2016-10-06T19:05:12.001900Z

in which case fallback may or may not be needed

tony.kay 2016-10-06T19:05:56.001901Z

I would, however, tend to use alternate logic. I would not be showing UI for making the object if it was possible for happy path to deny.

tony.kay 2016-10-06T19:06:04.001902Z

I'd show the object immediately for good user experience

tony.kay 2016-10-06T19:06:18.001903Z

and use fallback to fix things up on the (rare) unhappy path

tony.kay 2016-10-06T19:06:26.001904Z

otherwise you're waiting on the server, which is old-school thinking

2016-10-06T19:07:08.001905Z

hm yah, well for one thing there's server side validation of 'create-object params

2016-10-06T19:07:20.001906Z

so it may reject the user input, and need it to be reentered

2016-10-06T19:07:27.001907Z

i'm integrating with legacy system

tony.kay 2016-10-06T19:07:31.001908Z

OH

tony.kay 2016-10-06T19:07:32.001909Z

ok

tony.kay 2016-10-06T19:07:40.001910Z

yeah, that's the way to do it then

2016-10-06T19:07:46.001911Z

kk, thanks tony

tony.kay 2016-10-06T19:07:54.001912Z

I mean, you could validate the fields as you go (optimistically)

tony.kay 2016-10-06T19:08:10.001913Z

and not do the submit of final object till you're sure it is going to go ok

tony.kay 2016-10-06T19:08:22.001914Z

e.g. those validations could be server interactions

2016-10-06T19:08:32.001915Z

nods something to consider

tony.kay 2016-10-06T19:08:34.001916Z

but as we described it above should work

2016-10-06T19:48:27.001917Z

If there are are any more NYC area folks in here, Iā€™d like to host a Clojure Meetup about Untangled. RSVP here! http://www.meetup.com/Clojure-NYC/events/234676309/

2016-10-06T20:18:23.001919Z

any examples on tempids because todomvc?

2016-10-06T20:18:28.001920Z

docs?

2016-10-06T20:18:41.001921Z

i've read some of the source

2016-10-06T20:18:51.001922Z

I see it's like {:http://datomic.id/foobar 32 }

2016-10-06T20:19:22.001923Z

then I guess that updates the table in app-state, from {:table { :http://datomic.id/foobar { ..}}} to {:table {42 { ...}}}

tony.kay 2016-10-06T20:19:42.001924Z

You should use (om/tempid) at the UI to send temp ids into your mutation

tony.kay 2016-10-06T20:19:59.001925Z

the :<http://datomic.id/boo|datomic.id/boo> is part of our testing library

tony.kay 2016-10-06T20:20:27.001926Z

then return {:tempids {tmpid realid}} from your server mutation.

tony.kay 2016-10-06T20:20:36.001927Z

everything else is automatic

2016-10-06T20:21:33.001928Z

You should use (om/tempid)` at the UI to send temp ids into your mutation ` I don't quite follow, so

(defmethod mutation 'my/mutation [e k p]
{:remote true
:action ???} )

tony.kay 2016-10-06T20:21:57.001930Z

I'm sure todomvc does it this way...

2016-10-06T20:22:01.001931Z

k, looking

tony.kay 2016-10-06T20:22:24.001934Z

yes, :remote true should be sufficient assuming you don't need to modify the AST

tony.kay 2016-10-06T20:22:47.001936Z

the local action is just to put the data in your db, as normal (including the tempid)

tony.kay 2016-10-06T20:23:00.001938Z

tempid does NOT get called in the mutation!

tony.kay 2016-10-06T20:23:11.001939Z

would cause problems

tony.kay 2016-10-06T20:23:22.001940Z

tempid is called on the UI, and passed as a param OF the mutation

2016-10-06T20:23:36.001941Z

So

(defmethod mutation 'create-object [e k p]
{:remote true} )
is correct

2016-10-06T20:23:44.001942Z

then.. in api-mutate

tony.kay 2016-10-06T20:24:40.001945Z

remember that mutations are called more than once on the client (once for UI, and once for each remote). Tempid returns something diff every time šŸ™‚

tony.kay 2016-10-06T20:25:19.001946Z

The only way we differ from Om Next on this is that we handle the joining together of tempids from the server for you...which you normally have to do manually.

2016-10-06T20:25:38.001947Z

ok so in todomvc (update-in [:todos :list/items] (fn [todos] ((fnil conj []) todos [:todo/by-id id]))) (assoc-in [:todo/by-id id] {:db/id id :item/label text}))))}) the untangled engine automatically finds all references to this 'id' in tables, and links, etc

tony.kay 2016-10-06T20:25:42.001948Z

we don't really differ so much as implement

tony.kay 2016-10-06T20:25:58.001949Z

yep, rewrite of tempids is automatic

tony.kay 2016-10-06T20:26:02.001950Z

anywhere they appear

tony.kay 2016-10-06T20:26:06.001951Z

in app state

2016-10-06T20:26:08.001952Z

nice

2016-10-06T20:26:14.001953Z

you walk the whole of app state?

tony.kay 2016-10-06T20:26:26.001954Z

all you have to do is return {:tempids {...}} from server mutation

tony.kay 2016-10-06T20:26:45.001956Z

yes, we walk the app state...just a clojure prewalk, I think

2016-10-06T20:26:54.001957Z

Ok right on, thanks i'll give it a shot now

tony.kay 2016-10-06T20:28:06.001958Z

In regular Om, you have to say what your ID fields are called...it is an optimization so that migrate is a bit faster. In practice, it really isn't so slow (network delay will be much longer typically)...so we opted for ease instead of premature optimization. We can always work on speeding it up later if it becomes a problem.

tony.kay 2016-10-06T20:28:51.001959Z

For example, mark-n-sweep to remove missing data from responses is optimized by walking the query. We could do similar things for migrate that would speed it up. We really haven't found the need, though.

2016-10-06T20:55:13.001961Z

is this right?

(defmethod api-mutation 'booking2/create
  [env key {:keys [id]}]
  {:action (fn []
             (println "id: " (pr-str id))
             {:tempids {id 42}})})

2016-10-06T20:55:19.001962Z

i'm having issues

adambros 2016-10-06T20:55:40.001963Z

is that client or server?

2016-10-06T20:55:44.001965Z

server

2016-10-06T20:56:08.001966Z

my global state gets it's om/tempid replaced with ...nothing...

2016-10-06T20:56:37.001968Z

curiously 'booking2/create shows up in the global app state too

2016-10-06T20:57:04.001969Z

not sure why the mutation symbol would be put into global app state

2016-10-06T20:57:32.001970Z

(defmethod m/mutation 'booking2/create [env _ {:keys [id]}]
  {:remote true
   :action (fn []
             (m/swap-this! env assoc :new-booking-id [:booking/by-id id]))})

2016-10-06T20:57:44.001971Z

(nav-item {:title "create booking #2"
                :onClick #(transact! T [(booking2/create {:id (om/tempid)})
                                        (app/choose-tab {:tab :booking2})])})

adambros 2016-10-06T20:58:51.001972Z

is 42 what you are always returning?

2016-10-06T20:59:44.001973Z

yes

adambros 2016-10-06T20:59:57.001974Z

im not seeing anything obvious thats wrong

2016-10-06T21:00:06.001975Z

hmmm

2016-10-06T21:01:17.001976Z

got it working,

adambros 2016-10-06T21:01:36.001977Z

oO

2016-10-06T21:02:26.001978Z

(nav-item {:title "create booking #2"
                :onClick #(transact! T [(booking2/create {:id (om/tempid)})
                                        (app/choose-tab {:tab :booking2})])})
doesn't work

2016-10-06T21:02:29.001979Z

but `

2016-10-06T21:02:38.001980Z

(nav-item {:title "create booking #2"
                :onClick #(transact! T [(booking2/create {:id (om/tempid)})})
does

2016-10-06T21:02:44.001981Z

Oo

adambros 2016-10-06T21:02:52.001982Z

that looks like a bug

2016-10-06T21:03:12.001983Z

oh, sh* , I might be nuking the state in choose-tab

2016-10-06T21:03:22.001984Z

i thought it would show up in the DIFF at least, but maybe it happen quickly

adambros 2016-10-06T21:03:33.001985Z

nuking? thats not a good idea

2016-10-06T21:03:44.001986Z

let me confirm that's it

2016-10-06T21:04:49.001987Z

confirmed

adambros 2016-10-06T21:04:54.001988Z

lol >.<

2016-10-06T21:04:55.001989Z

yah choose-tab calls initial-state on the TabComponent

2016-10-06T21:05:01.001990Z

i thought it was a good idea at the time

2016-10-06T21:05:07.001991Z

fresh tab initialized

2016-10-06T21:05:51.001992Z

you can also switch tabs with merely a (om/merge Root {:current-tab (initial-state MyTabComponent nil)}) which is neat

adambros 2016-10-06T21:06:12.001993Z

well it sounds like that was the problem

adambros 2016-10-06T21:06:34.001994Z

shouldnt you be switching the tab ident to point to the new tab instead?

2016-10-06T21:30:55.001996Z

i am

2016-10-06T23:01:14.001997Z

@adambros is there a snapshot release with your tools ?

2016-10-06T23:01:24.001998Z

i could use a mixin right now

adambros 2016-10-06T23:06:57.001999Z

:loading:

adambros 2016-10-06T23:07:26.002Z

you could probably do a checkouts if you really want it