Fork me on GitHub
#om
<
2016-04-05
>
grounded_sage03:04:22

Is there a solid comparison of using Om Next to Reagent with Reframe? Seems to be the top two competing client side options

cjmurphy04:04:28

Nothing solid. Someone once looked at the demo Colin Yates put together of doing a table component/s with reframe, and pointed out (in terms of Big O speak) to Mike Thompson that doing the same thing would be less complex with Om Next.

iwankaramazow05:04:24

Is there a way to normalize the initial app state with parts of the query or the whole query not even on the root component yet? let's ignore the fact (for now) that parts of that query are on lazily loaded components which aren't available yet

tomjack05:04:48

you can pass {:state (atom init-state), :normalize true} as of some recent version

tomjack05:04:08

where init-state is already normalized (using whatever query you like)

tomjack05:04:59

..or not using queries at all

tomjack05:04:37

it occurs to me that in http://anmonteiro.com/2016/02/routing-in-om-next-a-catalog-of-approaches/, only the union query approach doesn't have this problem

tomjack05:04:14

actually that example doesn't use normalization, so not sure how that would work exactly

seanirby07:04:51

@cjmurphy: is that a video on youtube or something?

cjmurphy08:04:08

@seanirby: A Github: https://github.com/yatesco/re-frame-stiching-together. The conversation was in the reframe channel as I remember.

seanirby08:04:44

cjmurphy: thanks. learn anymore about follow-on reads since the last time we talked?

cjmurphy08:04:40

There was a chat in Untangled. I put up an example of them being used and someone said 'why did you use the customer key?'. Reason:- it doesn't matter which key you use - they are all in the root component anyway. (Assuming default db format).

cjmurphy08:04:29

I've since taken to expecting all to be re-rendered after every mutation, and not bothering with follow on reads by putting all mutations at the root a la Kanban. And sometimes using local state (with channels) where I don't want the updating upon every mutation to be happening.

seanirby08:04:42

the follow-on reads I was using were causing some bad performance issues for my app. these particular components were triggering mutations with a follow-on read that affected a very large component. i was able to sidestep the issue by not actually using follow-on reads but getting the large component via class->any and transacting with that instead

cjmurphy08:04:27

Oh that's interesting - not using this at all.

cjmurphy08:04:31

Did you go for the component one above, or the root component?

seanirby08:04:30

its not a descendant at all, just another component across the UI tree

seanirby08:04:40

descendant/parent

cjmurphy08:04:45

The example I gave had only the item (in many, under a parent component) being updated, which is good, but I can't get that to happen reliably.

cjmurphy08:04:22

Hmm yes - its difficult to work out what the logic might be. I hope one day we will be able to debug to answer the question - 'why is this component being re-rendered' when it is unrelated.

seanirby08:04:12

what is being rerendered in your case?

cjmurphy08:04:17

They were just some simple checkboxes. Github's gone to sleep for my profile otherwise I'd show you.

seanirby08:04:34

mine too 馃槙

cjmurphy08:04:52

Just real slow...

tomjack08:04:58

do you know about transform-reads?

tomjack08:04:48

(om/transform-reads reconciler your-tx)

cjmurphy08:04:06

Not at all I'm afraid

tomjack08:04:20

this tells you what your follow-on reads mean

seanirby08:04:28

i should probably update my local copy of the docs more often..

cjmurphy08:04:56

Are you using an ident there as the follow on? I never could get one of them working.

seanirby08:04:59

no theres, no ident or follow-on read happening. just getting the component that actually needs updating.

cjmurphy09:04:40

Oh yes - all within the parens.

cjmurphy09:04:34

Thanks for that code. Github is back and I found the

(om/class->any reconciler CodeDisplay)
you use. Will experiment with that idea on my checkboxes, which are still all always being rendered, despite the fact I couldn't achieve this problem on a minimal example: .

seanirby09:04:17

@cjmurphy: so in that example your GraphLineSelectionTextbox doesn't get rerendered ?

cjmurphy09:04:46

The other items don't get re-rendered. The one that was selected (or de-selected) does. So it works as you would want. And shows that an irrelevant follow on mutate read does the trick. So it works, but it is confused!

seanirby09:04:55

hmm, i might try it out later

artemyarulin11:04:14

Can anybody remind - what was a problem with cursor approach in the original Om? I remember David mentioned it in some talk, but I can鈥檛 find it

seanirby11:04:52

artemyarulin: never used om extensively, but the quick start mentions that cursors cause a deep coupling to the app state

cjmurphy11:04:25

'closing over' was the problem with cursors.

spoe11:04:37

Original om cursor are tree structures. But in applications you are not always presenting data in a tree form. Like you want to show the same data in different views. If in those places it's possible to change that data it's quite hard to synchronise those changes

cjmurphy11:04:48

Watch that talk from 5.30 onwards

artemyarulin12:04:55

Thank you all!

peeja15:04:55

Odd question perhaps, but: despite being an "alpha" version, is the om.core in 1.0.0-alpha32 considered production ready?

peeja15:04:23

I'm just hoping for a stable version of the old Om that runs on React 0.14

peeja15:04:35

Should I be waiting for a true 1.0?

anmonteiro15:04:47

@peeja: I'm pretty sure you can use it in production

peeja15:04:11

Awesome. Thanks!

anmonteiro15:04:32

IIRC there has only been 1 change targeting it

anmonteiro15:04:46

which was to improve compatibility with React 0.14

peeja15:04:09

Sounds pretty stable, then. simple_smile

anmonteiro15:04:17

this to say that it's pretty much the same as 0.9.0

anmonteiro15:04:23

only with React 0.14

peeja15:04:38

Right, I guess that makes sense.

tomjack17:04:28

what downsides would there be for representing "unique idents" as [:key] rather than [:key _]?

tomjack17:04:25

upsides: get-in and update-in just work. no need to use ~' in syntax quote or patch om to check for ns/

tomjack17:04:02

I guess it would mean that ident? should be extended to include vectors of length 1, which seems potentially troublesome

isak17:04:18

yeah you wouldn't be able to distinguish between QueryRoot and IdentExpr: https://github.com/omcljs/om/blob/master/src/main/om/next/impl/parser.cljc#L15

tomjack17:04:03

hmm. isn't [:foo :bar] both a QueryRoot and IdentExpr?

tomjack17:04:59

you don't expect QueryRoot and QueryExpr in the same places, so there is no need to distinguish there

isak17:04:17

maybe, i'm not sure what EdnValue is limited to

isak17:04:52

i'm writing a backend in a statically typed language and i just limited it to the types that might reasonably be used as an id

tomjack17:04:09

I don't think there is supposed to be any limitation simple_smile

isak17:04:45

can it be a map? a vector?

tomjack17:04:58

yes, it can be any edn value

tomjack17:04:41

just like the EdnValue in ParamMapExpr, where it makes more sense to use all kinds of stuff

isak17:04:29

well in my case i'm writing a backend for a relational database, where the ids tend to be simpler types, so i don't see any reason to worry about it

isak17:04:51

yeah in that context i didn't limit it, because i can see the need there

tomjack17:04:00

in any case I don't see any problem there for [:foo] unique ids

isak17:04:09

you're right that you would be able to figure out what is meant with that scheme, not sure if there would be any other problems

seanirby19:04:03

is there a way for nested components to query for top level data in the app-state without an ident?

tomjack19:04:29

look for :current-user

seanirby19:04:52

perfect, thank you @tomjack . i haven't seen that wiki page yet

tomjack19:04:59

(note that you need ~'_ inside syntax quote..)

seanirby19:04:27

to prevent automatic namespacing?

hlolli19:04:12

Is there any reason why it's not possible to do goog.style/setStyle on om.dom/img elements? (or maybe Im doing something wrong)

jplaza19:04:42

How do you add an html entity?

seanirby19:04:57

hlolli: can we see your code?

hlolli19:04:48

Well, the whole code is filled with comments and junk but basically this is inside a render function

(dom/img #js {:id "prufa" :src (:photo ((:slides @app-state) 0))})
(and the picture is visible) and in the repl I am trying this
(style/setStyle (gdom/getElement "prufa") :height 200)
or this
(style/setStyle (gdom/getElement "prufa") "height" "100")

anmonteiro19:04:14

@hlolli: om.dom "elements" are just React Element instances, they're not HTMLElement s

anmonteiro19:04:52

oh, actually your code is selecting an HTMLElement

seanirby19:04:09

hlolli: do you not need a "px" "%" suffix?

hlolli19:04:40

Well, my final goal is actually to try to create a basic slideshow with goog.fx.dom and seemingly for goog.fx.dom.resizeHeight a update style function is needed. It's somethimes diffucult to see the interoperability. Becayse the image href is inside a app-state atom, the image is shown by the way so that parts works.

seanirby19:04:11

looks right to me otherwise

hlolli19:04:28

by the way

(.-height (style/getSize (gdom/getElement "prufa")))
returns 600 so the brepl is sure connected. ps. bit of correction, im actually trying to use .resizeWidth (.resizeHeight doesn't exist seemingly).

iwankaramazow19:04:44

@anmonteiro: when manually normalizing initial app-state, should I provide :om.next/tables to the app-state (with :normalize false on the reconciler) ?

anmonteiro19:04:54

wait, what do you mean by "manually normalizing"?

iwankaramazow19:04:28

In the context of a router, let's say a user wants to supply initial data, that needs to get normalized for Om's graph magic. Problems: a) the query isn't on the root yet b) if there's code splitting, there isn't even a component available to get the query/ident for normalization. I'm might throw my router into an open source project, it's something I would like to somehow solve before doing this.

anmonteiro19:04:01

Yes I got that part

anmonteiro19:04:11

but you're not actually "hand-normalizing" your state, are you?

anmonteiro19:04:41

It's perfectly acceptable to call tree->db on a component that's not the Root

bendlas19:04:45

soo .. what's the meaning of {:value {:keys [ .. ]}}, does it have any semantics?

anmonteiro19:04:48

I've done that countless times

iwankaramazow19:04:20

Yea, but tree->db needs a component, what if it hasn't loaded yet as a <script>? Seems strange to load it just for normalization

iwankaramazow19:04:31

I might be overthinking stuff

tomjack19:04:18

@hlolli: you might consider trying react-motion; it may be a nicer fit

tomjack19:04:56

no warranty, but I've had good luck so far simple_smile

hlolli19:04:28

hehe yes! I've been working with that for some time now. I kinde-a gave up. I was able to animate, once, but animating the second time, never worked (cyclic animation).

hlolli19:04:02

but I could give it another try, I think I just coded it wrong.

tomjack19:04:32

note the om-bound-fn there, I think it is important

hlolli19:04:47

but I was able to change style with "display" "none" in goog.style/setStyle so Im getting closer to a solution.

tomjack19:04:55

not really sure yet whether that example fully works, but I haven't found more problems after adding om-bound-fn

hlolli19:04:10

ok thanks for this snippet

tomjack19:04:11

anmonteiro: it would be lovely to see a "routing with unions" example which uses normalization simple_smile

anmonteiro19:04:11

@tomjack: hrm, not sure what's the real problem there

anmonteiro19:04:30

the example would just be the same as I've written

tomjack19:04:16

you don't have any Ident, and your union query map is not associated with a component, which seems to cause an error ("Union components must implement Ident")

anmonteiro19:04:36

however, with :normalize set to true in the reconciler, and the initial state normalized with the first route's data

anmonteiro19:04:55

right, add the needed idents wherever they're needed

anmonteiro19:04:53

my post didn't focus on normalization or URL routing or any of those details, because the focus of the post was just to showcase different approaches people can take to implement routing in general

tomjack19:04:27

sure, thanks for that post. I will share my broken attempt to add normalization sometime

anmonteiro19:04:20

happy to look over it, and try to figure out what you might be doing wrong

tomjack20:04:17

putting (ident [this] [something ']) seems to cause tables with { ...} after normalization

tomjack20:04:50

not sure if this is a bug or a user error

anmonteiro20:04:24

that's expected

anmonteiro20:04:05

if you use [:by-id 2] you get table with {2 ...}, why wouldn't you get a table with {_ ..} if you use _ in an ident?

tomjack20:04:39

I expected no table, really, because db->tree looks for a "unique ident" like [:foo _] in [:foo], not [:foo _], as in "thinking with links"

tomjack20:04:37

so "you shouldn't return 'unique idents' from ident" makes sense to me, but then it's unclear how to add normalization to the union routing example -- unless we stop using unique idents?

anmonteiro20:04:10

I don't understand what you're trying to say

anmonteiro20:04:36

db->tree looks for a "unique ident" in queries

anmonteiro20:04:56

there's nothing preventing you from creating idents with [... _]

tomjack20:04:02

@hlolli not sure without playing with it, but I would try creating an Image component with a :keyfn specified in the factory

tomjack20:04:00

otherwise react-motion will just think it's the same image already animated, but with a new src

hlolli20:04:08

ok, so I should pass on the index from the root component into the factory of Image-slider?

tomjack20:04:13

maybe there is a component-less way to do this

tomjack20:04:41

well, pass the props. (btw you should not be deref'ing app-state in render... :) )

hlolli20:04:55

ok, I may add to the expectations of my skills that Im still bit of beginner. Thanks for this tip.

tomjack20:04:42

but now our app-state is mangled and there is no place for :app/about. hmm

hlolli20:04:41

in a factory, is this leagal (om/factory UIComponent {:keyfn [:key1 :key2 :key3...]}) ?

tomjack20:04:21

not really, typically it will just be :key1 if the props have {:key1 blah}

tomjack20:04:55

or it could be (fn [props] whatever) or #(whatever %)

hlolli20:04:04

so it's only possible to pass one property to a factory, Im probably misunderstanding.

tomjack20:04:28

props is a map there, the map you pass in

hlolli20:04:07

ahhh ok it becomes a whole map, got it!

tomjack21:04:13

now I guess one merge!s {:app/routes [{:routes/ident :app/home ...}]} instead of {:app/home ...}

tomjack21:04:08

but we'd like to avoid querying all routes I guess!

tomjack21:04:51

for initial state normalization we can add the :app/routes query just there. then for e.g. merging in a new route I guess we can pass that query again in the merge!

uwo22:04:49

@anmonteiro: In the solution you suggested yesterday

(defmethod read :root-query
  [{:keys [query target parser ast state] :as env} k params]
  (let [val (parser env query target)]
    (if (and (= target :search)
          (not (empty? val)))
      {:value (select-keys @state [:search/results])
       :search (om.next.impl.parser/expr->ast (first val))}
      {:value val})))
If we want to add more to the Autocomplete鈥檚 Query, say local variables, this would no longer work, no? val would contain more than one key for starters.
static om/IQuery
  (query [_]
    '[(:search/results {:query ?query})
      :local-value])

tomjack22:04:41

this was my question too

uwo22:04:00

@tomjack yeah, saw that. I wonder if that鈥檚 an actual bug

tomjack22:04:06

I mean, you can use (query->ast val) today, but your send will receive an invalid query

tomjack22:04:08

yeah, me too simple_smile

tomjack23:04:52

@uwo: a workaround will be to put all the search stuff under a single key, say :search, so that your remote query expr is like {:search [:search/results :local-value]}. but this does not seem always desirable. e.g. I have a remote which persists a few unrelated root keys to local storage, and I don't want to put those under a :local-storage key -- I should be able to add bits of state to local storage without changing the rest of my app

tomjack23:04:54

well. I guess you could make the remote query expr be {:search ...} without littering the app state with :search? this just seems silly, though