Fork me on GitHub
#om
<
2016-05-19
>
jasonjckn00:05:03

is there a way to colocate the initial global state pertaining to a particular component in the component defui itself

tomjack01:05:15

Maybe you could transact! in componentWillMount if you think that is sensible? ;)

tomjack01:05:25

I don't understand why you'd want that, but that is not saying much

ag02:05:14

OMG! I just don’t get it. I’ve been trying for like 2 days and still can’t make it work as I think it should work. Someone please help me. it’s driving me nuts. what I need: a) a component that renders list of items (data is in single array, every row has :color prop) b) one instance of this component that would show only items with :color :white c) another instance of this component that would show only items with :color :black

ag02:05:03

my instinct tells me that it’s gotta be 3 defui objects, - first, is Item with query like '[:id :color] and ident [:items/by-id id]. - second ItemsList with params and query that uses subquery of Item and in componentWillMount should update-query! with parameters taken from om/props this(?) - third Root that should use two factories of ItemsList and send the right props in

ag02:05:19

is this right?

ag02:05:12

how then queries should look like in ItemsList and Root?

selfsame02:05:53

@ag have you thought about doing this in your data? {:items/filtered {:white [[:items/by-id 5] 'etc]}

ag03:05:38

@selfsame: I just want to understand how it works… what is the right syntax for queries that have subqueries and also parameters?

ag03:05:23

how do I use parameters in something like this:

`[{:tree ~(om/get-query Node)}]
?

ag03:05:37

is this right

`[({:tree ~(om/get-query Node)}{:color ?:color})]
?

selfsame03:05:59

@ag gotcha, yeah that's right

selfsame03:05:50

then you'll have to set up a read method that uses the params and use om.next/set-query! to configure the components

selfsame03:05:13

and fwiw reads get invoked often - I like to cache heavy filter ops in the app-state with transact 🙂

jimmy03:05:52

@ag: why do you have : before params in your query ?:color. it's not correct btw

jasonjckn04:05:10

thank god for https://github.com/awkay/om-tutorial i would be lost without it

whistlerbrk14:05:11

Hi, new to Clojure/ClojureScript and om/next; Is it okay for me to provide the reconciler my app-state in an atom instead of letting it perform the normalization? The docs do this and say it’s okay for the Counter example, but I couldn’t find a more complex example. The reason I wish to do this is because I’m recursively building out my React components from a structure and filling in the already de-duped content which is separate that is my app state is atom { :structure {…} :data […]}

dnolen14:05:32

@whistlerbrk: you can pass :normalize false as an option when you create the reconciler

whistlerbrk14:05:30

@dnolen excellent, thank you

ag18:05:09

hey guys… I have a similar thing almost identical to the on in tutorial https://github.com/omcljs/om/wiki/Components,-Identity-&amp;-Normalization strange thing though it uses only one read method. it works fine (even with one), but I’m stumbled, how and why? so imagine defmethod read :list/two is never being called…

iwankaramazow18:05:30

That sounds pretty strange

ag18:05:42

oh wow… apparently sending entire AST to the server (which includes 2 lists) and resolving it there, returns entire dataset in one request and since the data is in the state, component never has to use read for list/two

iwankaramazow18:05:54

Hmm, but when you resolve it locally without a remote

iwankaramazow18:05:07

the parser will dispatch on both keys

iwankaramazow18:05:28

even when sending it to a remote, that sounds strange, I'll have to fire up a repl

ag18:05:52

yeah what I’m doing is this on the client for read :list/one I check if (if (get @state key) is not empty and if it is I send the entire ast to the server. on the server I am dispatching read methods for both list:one and list:two but then there I filter records (that come from one source) and since entire ast is on the server it fills up both lists. and sends them back to the client

iwankaramazow18:05:52

I assume there is a local re-read happening after the response has been merged?

ag18:05:26

oh wait… dammit … I have same read method dispatch in two places…

ag18:05:39

god, I’m awfully stupid

jasonjckn18:05:29

so I wrote this function small useful abstraction ontop of input textboxes

(defn text-edit [{:keys [on-key-enter on-key-escape on-blur]
                  :or {on-key-enter #{} on-key-escape #{}}
                  :as props}]
  (html
   [:input (merge props
                  {:type "text"
                   :on-key-down #(case (.-which %)
                                   13 (on-key-enter (.-value (.-target %)))
                                   27 (on-key-escape))})]))
the question I have is if I convert this abstraction to a defui, I don't how to do this, because om next separates out computed props from regular props, so this simple (merge props ...) that I did can't be done with defui

jasonjckn18:05:47

anyone know a way to write this abstraction with defui?

iwankaramazow18:05:32

have you seen the 'anonymous version' of defui?

ag18:05:22

oh… wow that’s interesting… ui thing I mean

jasonjckn18:05:28

@iwankaramazow: sorry not sure how ui answers my question, ui still requires computed and regular props separation

jasonjckn18:05:43

ok, I guess you just wrap it in a defn, and mix computed and regular, I wonder what the consequence of passing event handlers to regular props is

iwankaramazow18:05:01

I'm not sure, I think it has something to do with clojurescripts immutable data structures and React. @anmonteiro: could probably answer this

jasonjckn18:05:05

yah UI still separates computed and regular props.. I don't see how it answers my question

jasonjckn18:05:19

i can paste my new version of my code one sec

jasonjckn18:05:07

(defn TextEdit [{:keys [on-key-enter on-key-escape ]
                 :or {on-key-enter #{} on-key-escape #{}}
                 :as props}]
  (ui Object
      (render [this]
              (html
               [:input (merge props
                              {:type "text"
                               :on-key-down #(case (.-which %)
                                               13 (on-key-enter (.-value (.-target %)))
                                               27 (on-key-escape))})]))))

(defn text-edit [props] ((om/factory (TextEdit props)) {}))

jasonjckn18:05:23

(defui RootView
  Object
  (render [this]
          (dom/div nil (text-edit {:placeholder "foo"
                                   :on-key-enter #(js/alert "enter!")}))))

jasonjckn18:05:25

i guess you meant that

iwankaramazow18:05:16

honestly I would go with a pure function

iwankaramazow18:05:34

I misread the question, defui/ui has nothing to do with this

iwankaramazow18:05:56

just make sure there's a defui that passes the right handlers to the pure function

jasonjckn18:05:12

"defui has nothing to do with this" I could use functions a lot more than I have, any defui with just a render function could be a pure function

jasonjckn18:05:24

checking it out

iwankaramazow18:05:31

That's something you have to learn for yourself. As a heuristic I only use defui components when they absolutely need a query

dnolen19:05:18

looks pretty cool if you’re in Paris!

ag20:05:01

has anyone built tables with Next? I need to build a component that would take data (column definitions and rows)

ag20:05:18

is there sample projects I could still ideas from?

selfsame21:05:16

Is it bad if om/path doesn't match :om-path in prop meta?

dnolen21:05:01

@selfsame: hrm don’t remember

selfsame21:05:03

I gave all my top level components bogus idents which gives them a meta path like [[:selection :panel]] where the om/path is [:selection]

dnolen21:05:01

@ag I would just write a pure table component

dnolen21:05:09

and then some other component with queries can feed it

ag21:05:29

@dnolen: yup… that’s basically the plan.

isak21:05:52

does om.next have any opinion on how changes should be transmitted to the server? i.e., like this, except for updates: https://github.com/omcljs/om/blob/c5ce1fc09725280792c6d4ff15366680cbfe19f7/src/main/om/next/impl/parser.cljc#L15-22

mattsfrey21:05:44

wondering if anyone has opinions on whether start-up conditions such as whether a user is logged in or whether critical data has been fetched should be coditionally checked inside of a top level component for all the view these checks are in place for, or if this should be handled at the router level ?

jasonjckn22:05:18

i'm trying to change my todo list and add a new item to it, any om helpers for this in working with the normalized data?

jasonjckn22:05:20

(om/merge! reconciler
           {:todo/by-id {3 {:todo/id 3 :todo/title "new!"}}
            :widget/root {:todo/list [[:todo/by-id 1]
                                      [:todo/by-id 2]
                                      [:todo/by-id 3]
                                      ]}})
`

jasonjckn22:05:35

that just deletes my todo items #1 and #2

jasonjckn22:05:56

(because {3 {:todo/id 3 :todo/title "new!"}} replaces what was there previously in the state)

cmcfarlen22:05:16

@jasonjckn: The default merge fn is fairly simple. I had to write my own to handle cases like yours. You can pass a custom merge fn to the reconciler.

cmcfarlen22:05:20

(defn merge-fn
  [a b]
  (if (map? a)
    (merge-with merge-fn a b)
    b))

jasonjckn22:05:49

yah easy enough

jasonjckn22:05:19

i wish more of the query syntax was handled automagically

jasonjckn22:05:07

e.g. db->tree doesn't seem to handle {[:todo/by-id _] [*]}

jasonjckn22:05:25

step 1. implement a query engine that executes query plans against cookies, browser SQL storage, normalized local atom, a backend database, memcache, step 2, achieve simplicity in frontend code 😉

cmcfarlen22:05:15

I think we will see more purpose built backends (and server backends) for various tech and that will reduce the barrier to entry. om.next has some harder concepts so it will take longer to shake out.