Fork me on GitHub
#om
<
2016-02-05
>
hueyp03:02:39

(query [this] 
    `[{:panels `{:outliner (om/get-query Outliner)
                 :selection (om/get-query Selection)
                 :menubar (om/get-query Menubar)
                 :query (om/get-query Query)}}])
and then be smart about conj’ing id and :view to each?

hueyp03:02:15

and then the component view has an Ident [:panel/by-id <the id>]

hueyp03:02:34

actually nvm I got no idea simple_smile

selfsame03:02:10

@hueyp: hmm thats how the examples for unions work, will give it a try simple_smile

hueyp03:02:33

I’m not sure what the union is doing though since they have the same ident which is making me think I don’t understand unions simple_smile

selfsame03:02:26

@hueyp: yeah me neither. Looking at the demo, perhaps a union needs its own intermediary component with an ident that matches the type key https://github.com/omcljs/om/wiki/Queries-With-Unions#the-queries

tawus03:02:13

This weekend I want to give om.next another try. Last time I was stuck at returning errors from remote mutations. So my question is Is there a way to return errors from remote mutations ? If not how are other people handling these use cases e.g. login failure or update with validation errors ?

denik04:02:52

@selfsame: by generating the query expression you’re dropping metadata which causes Uncaught #error {:message "No queries exist for component path (fp.subdivide/Main fp.subdivide/Panel comp.outliner/Outliner)", :data {:type :om.next/no-queries}}

denik04:02:30

it should still work however

selfsame05:02:29

heya @denik, yeah the original example has subcomponent paths like [:data :outliner] and lets me transact or set-query! on the subcomponents

denik05:02:20

I think Idents are used to normalize nested state and not again until remote updates get merged in

selfsame05:02:26

aren't they also used for transact! updates?

denik05:02:55

I believe they aren't

denik05:02:01

which is why you have to #(swap! state update-in [:panel/by-id 5] f ) as your action thunk

selfsame05:02:59

aaah ok I was mixed up

selfsame05:02:56

idk I'm going to try not using a union and see if I can get better paths

denik05:02:59

small detour, I think every dev here could make use of: https://github.com/binaryage/cljs-devtools

denik05:02:14

@selfsame: hope it works out!

thosmos06:02:09

Has anyone here used Firebase as a backend DB for Om Next? On first look, it seems like it would mainly consist of parsing the query AST and translating it into firebase queries.

adamkowalski09:02:46

Hey is there any advantages to using multi methods for our read and mutate functions as opposed to using core.match for example?

nha10:02:59

There is no more IInitState in om.next, correct ?

nha10:02:55

I am trying to structure a login or register component, I have the following questions : - Should I have :user {:email "" :password "" ...} OR :user/email :user/password OR something else ? For now I have the first approach :

onEmailChange (fn [e]
      (om.next/transact! this '[(user/update {:email ~(-> e .-target .-value)}) :user]))
- regarding the mutations, how should I make my onSubmitLogin or onClickSignUp functions ? I guess I should have mutate 'user/update and 'user/create respectively
(defmethod mutate 'user/update [env key params]
   {:action (fn [] (info "What should it do here ?")) })

cjmurphy10:02:16

You would pass the username and password in params.

cjmurphy10:02:29

In mutate function update the state with them.

nha10:02:46

ok - then for the onSubmitLogin I should make another mutate with :remote ?

cjmurphy10:02:38

I got no experience with remotes 😞

nha11:02:19

No problem me neither. I am just trying to see what is the tool to use in this case.

nha11:02:35

Thanks for your help, again.

cjmurphy11:02:45

A swap! statement in the action. Because your data is normalized it is flat so that should be easy.

nha11:02:34

ok I'll try that thanks

selfsame12:02:27

@denik re: component Idents, turns out they do work in transact! if you turn on :pathopt in the reconciler https://gist.github.com/selfsame/2c7035a5f5f76ab72d6b#gistcomment-1690135

denik13:02:52

@selfsame: thanks, good to know!

Lambda/Sierra15:02:58

Is there any reason to implement om.next/Ident when using Datascript as a data source?

dnolen16:02:39

@stuartsierra: yes, idents are used to keep components in sync

dnolen16:02:03

also idents can still be used to speed up queries even if you use DataScript

Lambda/Sierra16:02:14

@dnolen: Thanks, makes sense.

mdhaney16:02:23

@thosmos: haven't tried it yet, but I do think Om-next would work great with a Firebase backend. Firebase data tends to be denormalized and I think Om-next would help a lot with managing it.

mdhaney16:02:06

@adamkowalski: I've been thinking about using core.match as well. Surprised more people haven't mentioned it.

Lambda/Sierra16:02:29

Still learning here: suppose I have a query that pulls data from a Datascript database. Some of the keys in my query are attributes in the database, other keys represent data I want to compute on-the-fly. if my understanding is correct, my read function has to filter out the "special" (computed) keys, call Datascript to query the "normal" keys, then call some custom code to evaluate the "special" keys and merge them into the result.

Lambda/Sierra16:02:54

Is that headed in the right direction?

dnolen16:02:18

@stuartsierra: I would minimize that as much as possible, doing that will make everything a lot more complicated

dnolen16:02:33

regardless of DataScript or not

dnolen17:02:00

the only time you should immediately reach to create some synthetic key is the case of a collection you intend to render

dnolen17:02:32

that may or not map to something in your data store :user/todos or whatever

Lambda/Sierra17:02:50

in other words, only use synthetic keys for top-level queries?

dnolen17:02:06

yes - it’s not that doing things differently isn’t possible

dnolen17:02:26

it’s just that at that point you might as well just completely re-implement parse yourself

dnolen17:02:44

and dispense with the read mutate pattern which is just a convention

Lambda/Sierra17:02:28

I suppose anything that I would generate for a synthetic key could just be loaded into the database beforehand.

dnolen17:02:03

if for some reason you decide to go down that path that’s what the query AST stuff is for

dnolen17:02:19

the cases where you just want to implement your own query evaluation thing

dnolen17:02:08

normally that’s narrowed to customizing remote queries, but you can generalize it

mdhaney17:02:07

So I have my root component with top level queries, and now I have to pull the correct data out of props to pass to each child component. Not too bad, but suppose I want to handle this in a more generic way - couldn't I just iterate over all my child components, call get-query for each, and then call parse passing it the components query and props? Kind of like how in Datomic you can run queries against :db-after after a transaction. Or is there an easier way that I'm missing?

dnolen17:02:29

@mdhaney: not really possible and would be going against the grain

bplatz18:02:31

@stuartsierra: I do this by having a multifunction for my merge-tree and merge-ident. If certain keys are incoming I will add extra datascript attributes to them at that point. Then my query is always clean.

bplatz18:02:02

i.e. I have a made-up datascript-only attribute called :this/user?... basically it takes standard user entity datoms and adds that to it, if the query key was [:this/user '_].

bplatz18:02:29

Then my read for that key can query where :this/user? is true.... but that attr doesn't sit obviously in my back-end datomic data store.

bplatz18:02:34

And for items that truly need to be computed at run-time, I just do that inside the component using om/computed

Lambda/Sierra18:02:08

@bplatz: Thanks. What are merge-tree and merge-ident?

bplatz18:02:09

Those are supplied to your reconciler as options. merge-tree handles all your normal query keys, merge-ident handles merging in any keys that are idents.

bplatz18:02:37

There are default implementations for both, but they are not really appropriate for datascript... just appropriate for using the default atom.

bplatz18:02:44

So you over-ride them with your own.

bplatz18:02:32

Those are the two default functions.

Lambda/Sierra18:02:13

@bplatz: I see. So you generate "synthetic" keys in the local application data while loading from a remote source?

bplatz18:02:30

Yes, exactly.

bplatz18:02:29

And in fact I sometimes do it at the remote... I'll just add the keys to the response. Depends on if I think it really is a client-specific thing.

bplatz18:02:39

Most of the times on the client though.

bplatz18:02:39

FWIW, here is my merge-tree

bplatz18:02:43

`(defn merge-tree [db data] (doseq [[k v] data] (merge-data db k v)) @db/conn)`

bplatz18:02:12

Then my merge-data is a multifunction dispatched off k

Lambda/Sierra19:02:00

@bplatz: Thanks, will investigate.

bplatz19:02:09

And FWIW, my merge-ident

adamkowalski19:02:31

Are there any more examples of using datascript with om next?

adamkowalski19:02:19

https://github.com/omcljs/om/wiki/DataScript-Integration-Tutorial I have looked at that and it seems like a good starting point, but I would just like to see a few more examples to wrap my head around how it all looks in a slightly larger demo

hueyp20:02:56

@bplatz @stuartsierra I’m contemplating this exact same thing regarding synthetic keys, thanks for the discussion!

nano23:02:08

Anyone have any example of passing a query to the cb function that's passed to the reconciler send function? Not sure what it's supposed to do. Say if I have app-state {:foo {:bar 42 :baz 23}} and my reconciler send wants to update :baz, would (cb {:baz 99} [:foo]) be a correct call?