Fork me on GitHub
#om
<
2016-02-21
>
drcode00:02:20

How are people using normalization with singletons? Is the best thing just to have a top-level db like {:singleton {nil {...}}} i.e. make the "id" of the ident nil?

anmonteiro00:02:46

@drcode: if it's a singleton, do you need to normalize it at all? simple_smile

seanirby00:02:08

I would like to get the value attribute of a sibling component in a click handler. I know I can use document.getElementById but I was wondering if theres a better way. I tried using a "ref" attribute but I couldnt find the dom node with a given ref string.

drcode00:02:15

@anmonteiro: Interesting question... it's a piece of atomic data that is needed by several UI components and needs to be fetched from the remote as needed... Should I be using the usual normalization mechanism?

anmonteiro00:02:29

@drcode: with only the information provided, I would opt to use links

anmonteiro00:02:43

have you gone through the Links tutorial?

drcode00:02:32

Yes, I agree links would work, I just can't wrap my head around the appropriate way to do remote fetching when links are involved...

anmonteiro00:02:48

in which part?

anmonteiro00:02:23

remember you always have the AST stuff to help you rewrite stuff

drcode00:02:54

@anmonteiro: If I understand what you're suggesting, it is: 1. Child component has link [:singleton _] in query 2. Parent "read" function says "Oh, one of my children is asking for top level item :singleton through a link, but I don't have it in the client yet" 3. Parent "read" function generates a remote that includes the top-level :singleton (My understanding is the parent needs to handle this, because if the child asks, the data returned from the remote will be pathed and not in the top level) 4. Remote sends top level :singleton to client

drcode00:02:13

@seanirby: I guess what I would do is find the shared parent between the two components, and try to get the value into that parent's state (via a callback sent to the children via om/computed)

anmonteiro00:02:10

@drcode: partly right, with the exception that you have control in all phases of the process

anmonteiro00:02:29

e.g. you can always override how things get merged when they get back from the remote

drcode00:02:16

@anmonteiro: Yes, I've tried to avoid doing that so far, but I agree that would be an easy way to solve this problem...

anmonteiro00:02:24

there's another alternative

anmonteiro00:02:38

:singleton is a top-level key in the parent

anmonteiro00:02:53

referred to by [:singleton _] in the children

anmonteiro00:02:14

you can just elide all the link stuff on children queries when sending them to the server

anmonteiro00:02:19

(or ignore them at the server — probably not the best solution)

anmonteiro00:02:43

because the parent is sending :singleton anyway in the top-level query

drcode00:02:02

@anmonteiro: OK thanks, lots of great suggestions! I will have to think about which route to take.

anmonteiro00:02:19

@seanirby: refs are only accessible from the component that owns the components with refs

seanirby00:02:47

anmonteiro: right, I can get the ref string by looking at the refs property of the parent, but I need the component not the ref string

drcode01:02:47

@anmonteiro: One last followup question: What is the benefit of using a link [:singleton _] instead of simply writing a read function for :singleton that simply pulls the value out of the top level of the state? Is it that om/db->tree can automatically resolve links, saving some parsing work, or is there a deeper reason for using links?

seanirby01:02:30

nvm, I see I was accessing the properties of the parent element

seanirby01:02:36

incorrectly

seanirby03:02:34

does anyone have any experience with using a database other than Datomic for om projects?

jimmy03:02:35

do you mean om next or om

seanirby04:02:55

nxqd: om next

seanirby04:02:18

nxqd: well actually, both

jimmy04:02:33

I can tell that in term of om next, it has the same query as datomic

jimmy04:02:09

I see that there is one person in this thread, try to build a datomic pull api for sql database

seanirby04:02:29

nxqd: yeah I want to use datomic, but I'm a bit inexperienced with server-side programming so I'd like to learn a technology thats a little more widely used if possible (SQL)

jimmy04:02:29

hmm, if you want to use sql for now, I'm pretty sure that you would do a lot more things to get it done

seanirby04:02:39

nxqd: right

jimmy04:02:50

since om.next is now in alpha state and it will try to simplify things a lot

seanirby04:02:07

maybe i'll just stick with datomic for now and hope someone builds a SQL interface in the meantime simple_smile

jimmy04:02:17

and the problem of backend regarding sql or query api -> sql or datomic is not its concern 😛

seanirby04:02:54

I don't follow your last statement

jimmy04:02:26

ah I meant, om.next uses datomic pull api for its query

jimmy04:02:11

in the backend you need datomic or another engine that parse the query expr to sql is none of om next concern.

seanirby04:02:44

ah ok. yeah that's right, i like that

seanirby06:02:59

in the om-next remotes tutorial, the reconciler is passed [:remote :search] for the :remotes keyword. I get why :search is there, but why :remote ?

iwankaramazow08:02:57

@seanirby: :remotes is nothing more than a vector of keywords representing remote services. In this case only the :search-remote gets used in the app. You can leave the :remote-remote out of the equation.

seanirby08:02:34

iwankaramazow: thanks

rauh09:02:43

I have an uncontrolled <input> (ie no :value specified), and if I do a set-query! in onChange it swollows the first character entered in the input. Then it works. If I remove the set-query! it works fine. Any ideas what goes wrong? (Currently working around by using a controlled input with get/set-state!)

jamesmintram09:02:06

@marianoguerra: so it looks like its used to introduce the namespace into the key - thanks simple_smile

seanirby09:02:14

rauh: can you post the code?

jamesmintram09:02:21

@anmonteiro: You mentioned a links tutorial above - can I ask for the link? (Not sure I have seen it yet)

rauh09:02:07

@seanirby: Can't reproduce it now in a minimal setting. I'll try to invesitgate it later. Gotta go now.

iwankaramazow10:02:34

A query: [{:a [:b {:c [:c/prop1 :c/prop2]} {:d [:stuff :other-stuff]}] Can I do something like

(defmethod read :a
  [{:keys [parser query ast] :as env} key params]
  {:value (parser env query)})
to properly parse :b :c :d? (note :c might be a remote and the other two might not be remote ...) Or do I have to solve this with custom functions ?

jannis11:02:20

You'll probably find out it works 😉

artemyarulin11:02:09

Hi, haven’t tried om-next for a couple of months and looks like I forgot everything simple_smile Can anybody give me an example of remote fetch with ident? I’m using ident and I have data partially available and would like to fetch data from the server in case it’s missing some props in the local state. Problem is that I cannot get ident identifier in send function. Does anyone have an example?

iwankaramazow12:02:55

@jannis: it doesn't work, it seems to only fetch to non-remote keys. No idea why and how 🙈 return {:value (parser env query true) } returns nothing...

anmonteiro12:02:20

@iwankaramazow: You need to recursively return remote to the toplevel

anmonteiro12:02:43

Tony's tutorial has an example of that

iwankaramazow12:02:42

Ah ok, thanks for the guidance!

jamesmintram12:02:41

So I have been looking at the om next join tutorial by @anmonteiro - and had a question about this sample: https://gist.github.com/jamesmintram/a0c6f9750de986a6f224#file-gistfile1-txt-L31 — If I wanted to add a Root node, which rould render the Item list - what would the Root node’s query look like? I have been trying to do something similar myself, I tried something like:

(defui Root
  static om/IQuery
  (query [this]  [(om/get-query ItemList)]))
and passing (om/props this) as the parameter to ItemList - but I get an error.

anmonteiro12:02:56

@jamesmintram: you cant steal queries from components

anmonteiro12:02:53

You need to put the query under its own key, e.g. [{:root (om/get-query ItemList)}]

Oliver George12:02:37

Just wanted to throw my weekend experiment into producing a relational db remote suitable for om.next

Oliver George12:02:52

Barely works but might be inspriation for someone.

Oliver George12:02:05

I'd love to hear that someone has a library for something like ethis.

jamesmintram12:02:14

OK - so I tried that - but that had knock on effects with needing my data to reflect that too. So I would then need {:root {:Items {…..

jamesmintram12:02:51

I guess the better question to ask is, how would the State data look in that sample to support what I am asking?

anmonteiro12:02:54

Yes, the app state needs to match the new shape of the queries

jamesmintram12:02:36

So how would I share the items between multiple subtrees? (Using Links I would guess) - but I am not sure how this would look in a concrete example.

anmonteiro12:02:41

Links only work for top level stuff

anmonteiro12:02:07

You'd want idents in this case

jamesmintram12:02:48

OK thanks! I will go away and bang my head against the wall some more to see if I can finally grok this! simple_smile

iwankaramazow13:02:17

Tony's tutorial says: process-roots only handles joins as new roots. It will not follow the branches of a union nor can it re-root a plain property. Is there any way to re-root a query including a plain-property?

tianshu14:02:46

Hello, everyone! I'm new to om.next, I have a few questions with integration with datascript. If I use datascript as the state storage, how can I merge the response from remote query? writing my customized callback function for send?

anmonteiro14:02:31

@doglooksgood: yes, override :merge in the reconciler

tianshu14:02:32

Thanks! I'm going to have a look at :merge.

tianshu14:02:35

BTW, how can I merge the server-pushed?

danielstockton14:02:18

@doglooksgood: You should know, there are parts that don't integrate well at the moment. Like set-query and query params.

tianshu14:02:48

Which one is better, using om to control remote request, or trying to synchronize the datascript and datomic?

tianshu14:02:51

Em.. A bad question, I guess. I'm should write demos first.

thiagofm15:02:06

Is there an easy way to get the current component from inside a component?

thiagofm15:02:55

as with (om/props this) I get props

marianoguerra15:02:16

@thiagofm: isn't this a reference to the component?

marianoguerra15:02:20

or you refer to the class

thiagofm15:02:58

To the class, such as StoreTab

marianoguerra15:02:19

maybe (om.next/react-type some-component) ?

anmonteiro15:02:41

or om/react-type

anmonteiro15:02:44

that should work too

anmonteiro15:02:11

(type this) might not work in advanced compilation, I believe

thiagofm15:02:26

What I wanted to do is: I have a tabbing component, so I save what is the active tab and then render it. I wanted to do it in a nice way, by just saving the factory of the component and passing it forward to be rendered if it's the active

thiagofm15:02:40

Wrong approach right?

thiagofm15:02:35

I think it works. om/react-type still works in advanced compilation @anmonteiro ?

thiagofm15:02:22

Also, is there a way to get the corresponding factory of a component? Or just the factory directly?

anmonteiro15:02:52

@thiagofm: haven't tried in advanced so I can't say for sure

anmonteiro15:02:50

no way to get the factory of a component, that's just a user concern

jimmy15:02:11

@thiagofm: if you just want to get the child component, you might want to try react ref

thiagofm15:02:55

I think I've got what I wanted. The problem now I'm having is more related to my lack of knowledge about clojure 😞

thiagofm15:02:23

Lets say I have (def tab 'Tab), how do I call (om/factory Tab)? I've tried (om/factory ~tab) but there's something wrong I'm doing

jimmy15:02:56

I'm not sure what you try to do but you may want this

jimmy15:02:08

(def tab-ui (om/factory Tab))

jimmy15:02:16

then just use tab-ui

thiagofm15:02:37

I do have that, the problem is that I have to load the factory dinamically

thiagofm15:02:02

Let's say I have 'Tab saved somewhere, how do I convert this 'Tab to a factory?

thiagofm15:02:29

(missing some macro knowledge)

anmonteiro15:02:13

@thiagofm: not sure why you'd need to do that, in any case you need to syntax-quote before unquoting

`(om/factory ~tab)

thiagofm15:02:42

@anmonteiro: http://pastie.org/10731361 example of code that doesn't work

thiagofm15:02:44

given that active-tab-component is 'Tab, why wouldn't this work?

anmonteiro15:02:07

because a factory is not a react element

thiagofm15:02:58

(`(om/factory ~active-tab-component) (om/props this)) still gives me TypeError: cljs.core.sequence.call(...).call is not a function

thiagofm15:02:12

It looks as I can't have a dynamic om/factory in the middle of my code 😞

artemyarulin19:02:34

Can anybody give an example of remote fetch where part of the data already available? I’m getting data from the cache and would like to make remote fetch if props are missing in the state. Couldn’t figure it out

hueyp19:02:45

the awkay tutorial has some framework-type-functions for doing this

hueyp19:02:40

I haven’t used it but I think you’d do something like fetch-if-missing for your leafs, and then recurse-remote for your branches

hueyp19:02:01

it recursively calls parse

artemyarulin19:02:09

@hueyp: Oh, thank you! I’ll have a look

hueyp19:02:27

I think they get a shoutout in the tutorial too, lemme find page 😜

artemyarulin19:02:27

Hm, the thing that I don’t understand - send function has only query itself. What if I’m using ident like :customer/by-id 22 {:name John} and would like to fetch missing picture. How can I pass this 22 to the send function?

artemyarulin19:02:14

or more general - getting customer by id for example

hueyp19:02:17

idents can be a part of queries

hueyp19:02:44

I ran into trouble having them in components, the indexer was unhappy, but I think that might be changed on master

artemyarulin19:02:14

so - in my read function I should modify query and add needed info there before it’ll be passed to the send function?

hueyp19:02:14

but [{[:customer/by-id 22] [:name]}] is parseable

hueyp19:02:32

I’m not 100% sure what you’re after

hueyp19:02:45

but you probably shouldn’t need to modify the query for basic stuff

artemyarulin19:02:43

yeah, probably I’m doing something wrong. Talking about your example [:customer/by-id 22]. If I have such query in my component, will 22 be accessible in send function?

hueyp19:02:50

the send function just gets the query … that said, when you parse the query, the :key for the expression [:customer/by-id 22] is [:customer/by-id 22] while the :dispatch-key is :customer/by-id

hueyp19:02:05

having that in a component though I couldn’t get to work, but again, I think it might be different on master now simple_smile

hueyp19:02:14

I mean, it worked in that it sent the query and parsed

hueyp19:02:35

but didn’t work in that it disjointed the componets, the indexer couldn’t connect query to component (sorry for lingo)

artemyarulin19:02:08

Got it, most probably I’ve done something wrong cause in my send I have object like {:remote [:customer/name :customer/second-name]}

artemyarulin19:02:44

without any keys. I guess I should re-read the tutorial

hueyp19:02:21

yah, I dunno 😜 you have total control over the AST / merge so you can always make whatever you need to work for you simple_smile

artemyarulin19:02:04

yeah, thanks! BTW - quick question: I’ve seen people using :some-prefix/prop-name as a keys for the state. Is it just a convention? Can I use simple :prop-name?

artemyarulin19:02:13

nice, thanks again. Any suggestion or maybe community already figured out the right way of creating router with om-next?

hueyp19:02:15

I don’t think there is the one true way, but there are a few different projects on github

hueyp19:02:21

with their own takes

grzm20:02:01

Probably off-topic. I'm using ring on the backend of an om.next app and getting Problem accessing /api. Reason java.lang.AbstractMethodError for POSTs (where /api is my remote endpoint) GETs are working fine. Anyone encountered this type of error when working with remotes? I'm println'ing the heck out of my code and feeling dirty doing it

grzm20:02:44

What's a bit maddening is that the mutate that's expected to happen is happening: the correct data is getting persisted to the database. So it seems to be something happening after the mutate completes.

thiagofm20:02:35

How can I pass params to a component that isn't om/props?

grzm21:02:11

thiagofm: can you give some context?

thiagofm21:02:53

I can't (tab-comp (om/props this) my-params)

thiagofm21:02:22

with (def tab-comp (om/factory ..))

grzm21:02:35

(tab-comp (merge (om/props this) my-params)) ?

thiagofm21:02:54

So I have to merge? 😞

thiagofm21:02:14

I mean, is this good practice? Maybe I'm doing something wrong...

anmonteiro21:02:17

@thiagofm: this is what om/computed is for

thiagofm21:02:50

@anmonteiro: the example in the docs for it is pretty poor, can you give a small example given that I need to also pass (om/props this)?

anmonteiro21:02:24

(om/computed (om/props this) {:a 1})

thiagofm21:02:54

May I update docs?

thiagofm21:02:16

(some-widget (om/computed props {:delete (fn [e] ...) :update (fn [e] ...)})) it's a bit unclear that props is (om/props this), at least for me 😞

anmonteiro21:02:36

the description does make it clear.

grzm21:02:50

@anmonteiro: in that case you don't pass anything to tab-comp, do you? It's just available in this via om/get-computed

anmonteiro21:02:15

@grzm: computed returns the props + any computed information you add

thiagofm21:02:58

Is anybody writing a book about om next? Or screencasts? Or anything? 😛

thiagofm21:02:42

Okay, so computed props passes down the props separated from the params/props I've provided

grzm21:02:06

has anyone tried the om-next-demo recently? I can't get it to create new todo items

thiagofm21:02:21

I keep receiveing Error: No queries exist for component path (haxlife.components.window/Window haxlife.components.window/GameWindow haxlife.components.tab/Tab haxlife.components.tab/SkilltreeTabLink) everytime I do om/transact. The component has a query and everythimg, but still doesn't work

thiagofm21:02:43

I mean, it works and all, but I get this error in the console

grzm21:02:07

thiagofm: does the query in the component get composed all the way down to the root? (it's included in root query?)

thiagofm21:02:55

I only get this message when I pass props down the stack using computed (or just passing down the props also give me errors)

grzm21:02:33

same errors regardless of whether you used om/computed?

thiagofm21:02:01

yes, error happens whenever something gets passed down the component

thiagofm21:02:12

okay, I think I know what's the problem

grzm21:02:42

I had the same error when I was skipping a middle component. Say I had "root -> parent -> child", Root was including child query directly, so the initial render was correct. On re-render, since the parent query wasn't part of the root query, I got the error you're getting.

thiagofm21:02:59

I've specified a query, for example :foo, and the same query :foo is used by another component

thiagofm21:02:10

I get the error, but everything works perfectly

thiagofm21:02:22

I've just removed the query and now I don't get the message anymore

grzm21:02:43

Yup. sounds like what i had

thiagofm21:02:56

Is this a desirable behaviour: queries can only be run by one component?

grzm21:02:00

I'm not sure what you mean: all of the queries in each component (and not call components need them) should be included in the root query

thiagofm21:02:54

Okay. An example: Let's call root component Page. In Page I have (first (om/get-query Content/Title)) and (first (om/get-query Content/Text)) In Content/Title I query the [:title] In Content/Text, for some funny reason, I have [:title]

thiagofm21:02:04

Then I get this error

thiagofm21:02:15

It looks like a bug to me, because it makes sense to perhaps query the same thing in different places, as long as you specify that in the root component you should have it working

grzm21:02:32

What's the full query look like for Page?

thiagofm21:02:00

It's just a made up example of how I think I can reproduce that. But here: static om/IQuery (query [this] (first (om/get-query Content/Title)) (first (om/get-query Content/Text)))

thiagofm21:02:33

if both components query the same stuff, and one is children of the other, you get this error

grzm21:02:15

Shouldn't that look like [{:title (om/get-query Content/Title) :text (om/get-query Content/Text)}]` or something?

thiagofm21:02:41

I'll make a better writing over that problem, better than wasting your time, I've found a workaround for it

thiagofm21:02:53

Might be for that reason, I'm not using a hash

hueyp21:02:21

I’m not sure you can compose queries without using a hash

thiagofm21:02:08

s/hash/map but yeah, sorry. Things have been working without using a map though, so I didn't have this problem yet

grzm21:02:11

And your query is essentially just (query [this] (first (om/get-query Content/Text))

hueyp21:02:04

you can do stuff like first, into, etc and create valid queries, but I don’t think it ultimately works with the indexer — it needs certain meta-data on the query

hueyp21:02:23

so you can end up with things working but as soon as you transact from a component it is unable to find a query path between the root and the component

hueyp21:02:30

this has been my experience so far

thiagofm21:02:09

I see 😞 I've been using that way because it was the first workable solution I could get, great to know that

anmonteiro21:02:16

you can definitely use into and the sorts

anmonteiro21:02:26

meta-data is only attached when binding the query and the params

anmonteiro21:02:35

what you can't do is steal queries from child components

hueyp21:02:41

(into [:id] (concat (om/get-query Child1) (om/get-query Child2)))) ?

anmonteiro21:02:43

which is clearly the case

hueyp21:02:56

I mean, I did that, and Child1 and Child2 are not indexed

hueyp21:02:07

because the metadata is gone

anmonteiro21:02:21

right, but that's not valid composition anyway simple_smile

hueyp21:02:21

thats kind of what I mean when I don’t know how to compose without it being a join (map)

hueyp21:02:26

just making sure !

anmonteiro21:02:25

the DashboardItem query in the unions tutorial uses functions:

(query [this]
    (zipmap
      [:dashboard/post :dashboard/photo :dashboard/graphic]
      (map #(conj % :favorites)
        [(om/get-query Post)
         (om/get-query Photo)
         (om/get-query Graphic)])))

hueyp21:02:44

yah, but that ends up with a map, and conj maintains meta-data

anmonteiro21:02:56

into also maintains metadata though

hueyp21:02:17

yes, but you can’t ‘combine’ two queries without there being a join / union … right ?

thiagofm21:02:43

That case also doesn't apply very well to my project because I'm using datascript 😞

thiagofm21:02:55

But yeah, learning everyday!

anmonteiro21:02:19

query composition has nothing to do with the default database

grzm21:02:31

thiagofm: using datascript should only affect your parser, shouldn't it?

thiagofm21:02:59

Well, I didn't have a case with complex queries, I'm just querying key/value atm

thiagofm22:02:15

I also could do a complex query in datascript, name it :complex-query and then on (query [this] [:complex-query]). This is why I think I won't have this problem

thiagofm22:02:29

I'm probably also doing everything wrong, but yeah, first project

thiagofm22:02:03

All I care is if things show up as expected in the browser

grzm22:02:07

I feel your pain, thiagofm. Lots of stuff to learn right off the bat

jannis22:02:33

@thiagofm: As a start I'd try to get a few Om Next components with queries and a simple parser against a map or atom app state to work, and add DataScript in a separate step.

grzm22:02:09

I found writing my own devcards useful

jannis22:02:13

AFAIK there is no project yet that translates Om Next queries to DataScript queries yet, so your :complex-query idea would be a reasonable start. Once that works, it should be fairly straight-forward to generate DataScript queries automatically, with special conversion rules for idents and global links.

grzm22:02:10

Can someone explain what this line in the om-next-demo does? It looks like it's just calling an event. https://github.com/swannodette/om-next-demo/blob/master/todomvc/src/cljs/todomvc/core.cljs#L69

anmonteiro22:02:40

@grzm: returns the event

anmonteiro22:02:14

it's not meant to work, it's incomplete

grzm22:02:21

Oh, crikey. Really?

grzm22:02:31

Well, that explains a lot 😉

thiagofm23:02:15

I'm trying to build two of the same component, but with different props, I get the "Encountered two children with the same key" error. How do I circunvent that?

cjmurphy23:02:43

That's a React error message I believe. You need to tell React how to construct keys.

cjmurphy23:02:56

Example: (def grid-row (om/factory GridRow {:keyfn :id}))

cjmurphy23:02:32

:keyfn value is what React gets.

cjmurphy23:02:13

So if your component instance has an :id that is different to the other instances you should be right.

cjmurphy23:02:40

In the Chrome console look for $null as the React id.

thiagofm23:02:53

What about ident?

cjmurphy23:02:17

Not sure it is important for React.

cjmurphy23:02:37

Your ident may happen to also use :id.

grzm23:02:31

ident is for the reconciler. :keyfn is what React uses to identify components

grzm23:02:58

one place you can see :keyfn being used is in the element ids in the generated markup

thiagofm23:02:09

Okay, what do you mean by "if your component instance has an :id", how do I specify that?

cjmurphy23:02:40

In its query, and in its props.

cjmurphy23:02:10

Look at the Kanban demo. It uses :id for everything.

thiagofm23:02:15

(def tab-link-comp (om/factory TabLink {:keyfn :name})) like this? Given that I have a :name computed prop

cjmurphy23:02:35

Yes that would be fine too.

thiagofm23:02:41

Hm, didn't work 😞

cjmurphy23:02:52

If you don't give a :keyfn you will get $null.

thiagofm23:02:08

Yeah, still getting $null

cjmurphy23:02:16

The $null will tell you which component is giving the problem.

cjmurphy23:02:42

:name may not be in your props. You can assert for it.

thiagofm23:02:43

In my component I have(so it should be in my props): (let [{:keys [name]} (om/get-computed this)] But then I can't {keyfn :name}

cjmurphy23:02:22

You have to assert for it as well.

cjmurphy23:02:21

_ (assert name "Every line must have a name")

cjmurphy23:02:24

Put the _ if it is within a let statement - a little quirk.

thiagofm23:02:09

Okay, gonna try that tomorrow, thanks

cjmurphy23:02:38

Not sure what you mean by can't {keyfn :name}. Putting {keyfn :name} in your component factory function is all that needs to be done. And then no more $null - as long as the component has a prop value for :name.