Fork me on GitHub
#om
<
2016-01-25
>
steveb8n01:01:41

it correctly migrates tempids and queries work - can be verified in app or in integration test

shriphani02:01:04

Hi, I am trying to get some stuff done with clojurescript/om. Essentially I want the state to have file input and on-change do something with the contents. This is what I have - I ideally want to print something out to the console: https://www.refheap.com/114034

andrewboltachev02:01:15

(1) It's unlikely correct that you put dom/input into state. Was there specific reason for that?

shriphani02:01:27

Hi @andrewboltachev - sorry my cljs is quite rusty - I only fiddle with the browser occasionally.

shriphani02:01:39

and my react is quite poor as well simple_smile

shriphani02:01:47

how would you recommend I do this ?

andrewboltachev02:01:01

so, you're to use modern HTML5 shims to get file content

andrewboltachev02:01:35

well, then you're state is likely to be empty

shriphani02:01:36

my end goal is (i) user uploads a file that is a bunch of cljs maps (ii) we parse it and render it (iii) user edits it and we save it back to disk.

shriphani02:01:52

it is empty initially.

shriphani02:01:55

so do you suggest I put this outside the state and on-load update some other state - which typically renders the parsed cljs ?

shriphani02:01:29

sure take your time

andrewboltachev02:01:55

@shriphani: btw, do you want to use Om or Om Next?

shriphani02:01:17

umm which is better ? I just googled for a tutorial and went with whatever came up

andrewboltachev02:01:19

well, you're using Om already

andrewboltachev02:01:37

om/root is Om function

shriphani02:01:38

well I have written 2 expressions in it so it is not like I am committed.

andrewboltachev02:01:06

btw, did you go through tutorials?

andrewboltachev02:01:35

@shriphani: well, anyway there's something that should work https://www.refheap.com/114036 (or not, you test it)

shriphani02:01:37

just the first one that gets you a contacts app.

shriphani02:01:58

@andrewboltachev: weirdly I get no console output when I use your example.

shriphani02:01:24

that does produce output on the console

andrewboltachev02:01:23

btw, what browser are you using?

shriphani02:01:21

also I fiddled with it enough to get access to the files selected

andrewboltachev02:01:00

@shriphani: Please note that I've used js/console.log, which is better at prining raw JS values. You're on Google Chrome it would be possible then to explore it easily

shriphani02:01:10

yeah I noticed

andrewboltachev02:01:18

Whilst println is better for CLJS values

shriphani02:01:23

I’d been using println till then and it was a plainly worthless

shriphani02:01:27

thanks a bunch

andrewboltachev02:01:56

Also, you might check out React's main tutorial for better understanding https://facebook.github.io/react/docs/tutorial.html

andrewboltachev02:01:10

At least I did go through it

tmorten02:01:24

@steveb8n: sweet! This is good stuff. Do you think the way it works using the default-merge is by design?

shriphani02:01:31

@andrewboltachev: ok I was able to print out file contents to the console - I was wondering - if I make another component and make it render something in app-state, it should pick it up once the file-load is done correct?

steveb8n02:01:34

@tmorten: I didn’t dig deep into the various merge options. I saw merge-tree in other peoples code so I went with it. seems to work in that project and the app I’m working on

andrewboltachev04:01:48

Does anyone have routing in Om Next working?

steveb8n05:01:50

looks good so far

andrewboltachev05:01:47

sorry @shriphani Just were really busy

shriphani05:01:42

@andrewboltachev: no worries - I actually got it done.

shriphani05:01:48

thanks a lot for the pointers.

shriphani05:01:54

it looks pretty ugly.

steveb8n05:01:59

one nice trick I’ve noticed is that if I match the server routes to the client routes then I get automatic support for deep linking into the app. that’s a nice property

andrewboltachev05:01:44

I didn't think about delegation

andrewboltachev05:01:02

i.e. to invoke parser from read-fn

andrewboltachev06:01:07

@steveb8n: though it fetches data for all routes at once, doesn't it?

steveb8n06:01:32

@andrewboltachev: yes but that works in my current use-case since my routing is for editing different parts of a graph in one page

steveb8n06:01:59

might not suit other types of apps I suppose

andrewboltachev06:01:24

I tried to play with set-query!, and that were working just ugly

steveb8n06:01:50

agreed. I’m waiting to see all that discussion settle on a solution before exploring

andrewboltachev06:01:58

i.e. probably it can be called only from some places/at some moments with specific params

steveb8n06:01:43

exactly, it seems like those “helpers” are still being evolved by various folks in this channel

steveb8n06:01:32

I haven’t seen another sample app showing the top down approach yet so I’m sticking with total query until then

andrewboltachev06:01:53

@steveb8n: do you have recursive component btw? for graph node?

andrewboltachev06:01:16

or, reading fns resolve that stuff

andrewboltachev06:01:22

'cause graph isn't tree

steveb8n06:01:22

no recursive ui in my app although may need it in future

andrewboltachev06:01:57

can't get query params working

andrewboltachev06:01:39

@steveb8n: don't you have ones?

andrewboltachev06:01:02

like that "finger to the sky" programming style

steveb8n06:01:11

@andrewboltachev: do you mean om query params or route query params?

andrewboltachev06:01:36

well, I'll map route query params into Om ones

steveb8n06:01:59

@andrewboltachev: I am using them but don’t have an example in my public github project. you have played with this right? https://awkay.github.io/om-tutorial/#!/om_tutorial.D_Queries

andrewboltachev06:01:38

Like I said, Om ones work now

steveb8n06:01:57

I’m doing the same. Using closure to parse params from url in a cljs parser multi-method and calling that when building remote queries in the client parser

steveb8n06:01:42

this is nice also because when testing I can replace the cljs multi-method with a clj mock for reading the browser url

andrewboltachev07:01:34

Seems bidi doesn't have way to handle ?a=b&c=d -> {:a "b" :c "d"}

steveb8n07:01:00

exactly, that’s why I’m using closure with bidi

andrewboltachev07:01:23

Wait, 'cause it doesn't have?

steveb8n07:01:48

use bidi for the path part and om query for the params

andrewboltachev08:01:10

routing started to work, but now it doesn't read from remote...

andrewboltachev08:01:03

@steveb8n: btw I agree on the point: "top-down" is what always wanted

nano10:01:50

@steveb8n: ah, that's a nice solution!

nha14:01:35

Following the om tutorial with "1.0.0-alpha28", is the om/from-history fn broken ? it always returns nil for me.

dnolen14:01:24

@nha: it’s possible, but you need to be on a latest version of ClojureScript for it to work correctly for sure

nha14:01:39

Ah right. Will update simple_smile

nha14:01:24

Alright it is working now with the latest clojurescript.

nha14:01:00

(maybe I was doing something wrong before though )

nha14:01:13

Ok looks like it is loosing it after a Reload (from boot-reload).

nha14:01:31

Not that surprising I guess.

asolovyov14:01:17

should I ask questions about om/next here or in #C0DT1AZD3?

asolovyov16:01:57

cool! so here is the thing: I return {:value nil :auth :non-interactive} in my read function, and when I do (my-parser {:state (atom {})} [:whatever] :auth) I get nothing. When I read remote-sync-tutorial I got an impression that it should return :non-interactive? Anyway, :remotes of my reconciler are [:remote :auth] and :send function is never called. I'm not completely sure how to debug this...

tony.kay16:01:20

Have you read the Om tutorial on db format, reads and parsing?

asolovyov16:01:21

@tony.kay: I think I did, but surely I've tried to jump before myself?..

tony.kay16:01:33

In the community resources in Om wiki.

tony.kay16:01:03

if you are returning :value nil and expecting a good result from read, then you have not read enough simple_smile

asolovyov16:01:09

when I do (my-parser {:state (atom {:whatever :x})} [:whatever]), it returns my :whatever simple_smile

asolovyov16:01:36

well... I'm not expecting a good result, but even if I return anything in :value, I get nothing for remotes

asolovyov16:01:51

that's what I'm puzzled about...

tony.kay16:01:53

for remotes, you need to return a :remote key, not a value

tony.kay16:01:11

you have a choice: :remote true, or :remote ast...where :remote is you remote name

asolovyov16:01:30

and ast is a query-like thing?

tony.kay16:01:34

ast comes in env

tony.kay16:01:45

it is a query turned into an Ast so you can transform it

tony.kay16:01:59

see query->ast and ast->query

tony.kay16:01:21

Ah, I see you did return a remote...you just called it auth. Yeah, you want an ast, not a keyword

asolovyov16:01:23

{:value nil :auth true} worked

tony.kay16:01:31

right, it is sensitive to real booleans

tony.kay16:01:37

truthy isn't good enough

asolovyov16:01:41

ok, that's a bit more understandable

asolovyov16:01:04

what do you usually return in remote?...

tony.kay16:01:25

true if I don't need a transform, and an ast if I do simple_smile

tony.kay16:01:34

got a meeting...good luck!

drcode16:01:41

@asolovyov: The steep learning curve of Om Next is what makes it so fun simple_smile

asolovyov16:01:06

@drcode: 😄 well, I really like when I can jump in and do something :))) it's a bit different in this case simple_smile

drcode16:01:32

@tony.kay: Thanks btw for your resources, helped me through several difficult spots in the last couple of weeks

asolovyov16:01:34

I wonder if it's possible to render stuff without explicitly defining factories everywhere...

bplatz17:01:24

I'm merging in external novelty with om/merge! and re-rendering is working great keys explicit in the merge map. However there are other keys I want to also force re-rendering on.

bplatz17:01:58

Is there a utility to force re-render of all components of a given key (or ident?).

bplatz17:01:15

I don't see one in the documentation wiki anyhow.

dnolen18:01:00

@bplatz: no you do that by putting those keys into the transaction

bplatz18:01:02

There is no transaction, just a stream of datoms. I can wrap everything into om transactions if need be but I was expecting merge! To help avoid that.

bplatz18:01:13

So if I understand it correctly, om/merge! works well but only for items that affect a single key (or ident). If you have novelty that might impact multiple keys, you need to instead use om/transact! as it is the only thing that allows multi-key re-render.

bplatz18:01:39

And if that is correct, I'm not sure why not just wrap all external novelty in om/transact!, I can't think of a real need for om/merge!.

asolovyov18:01:14

somewhy when figwheel reloads my app, I get an error that reconcile! can't call ((:render st)), where st is {:normalized false, :queue [], :sends-queued false, :queued-sends {}, :queued true, :t 1}. I wonder what's that and how do I fix it?

anmonteiro19:01:55

@asolovyov: that's probably caused by multiple calls to add-root!

anmonteiro19:01:03

e.g. on reload

asolovyov19:01:24

@anmonteiro: ah! that could be, but what's the right way to re-render then?

anmonteiro19:01:52

@asolovyov: I've recently written about writing reloadable code in Om Next. See if this helps: http://anmonteiro.com/2016/01/writing-om-next-reloadable-code-a-checklist/

asolovyov19:01:20

you don't mention :jsload-callback anywhere...

anmonteiro19:01:37

"I imagine variations of it can be used as a Figwheel reload hook."

anmonteiro19:01:55

I do, just before the code snippet at the end

anmonteiro19:01:43

it also helps if you're running Om's master

asolovyov19:01:49

ok, force-root-render sounds ok

asolovyov19:01:00

but I've removed jsload-callback right now and everything works fine...

asolovyov19:01:03

that's interesting simple_smile

anmonteiro19:01:31

@asolovyov: you don't need js-reload if you're calling that example function on reload

anmonteiro19:01:38

e.g. you have an invocation in your code

asolovyov19:01:55

right, I'll build something like that

asolovyov19:01:54

nice, now everything's good, thank you!

futuro19:01:00

If I'm using datascript to store my app state, is ON's reconciler able to merge in external novelty from the read fn for me, or do I need to extend/adapt/something the reader?

futuro19:01:56

Also, though I'm late to the discussion, w.r.t routing in ON, I have one <div> that I swap various components onto, as opposed to having one root component that contains every other component (which is what it sounds like other people are doing, but I'm not sure)

tmorten19:01:50

So I'm curious how you all have been handling form data in om.next. In om.prev, I would mutate the individual keys in the cursor...with Om.next I've been loading into local component state and using a single transaction to update the record data. Anyone else doing anything differently?

noonian19:01:39

At one point I had all my forms in my app state using [:form/by-id “a-form”] which worked ok. Then when you submit or whatever you can deal with mapping that to the actually “source of truth” data in the app state.

tmorten19:01:28

Seems like I've been doing it wrong by loading into local state, and perhaps (according to React docs), I'm doing it anti-pattern style (wouldn't be the first time for me)

futuro19:01:14

@tmorten: Are you saying you should om/transact! every change to the form, or that you should store the use input locally then transact! it when the user submits it?

tmorten20:01:51

@futuro: Essentially, that was om.prev style, transacting on every change of key inside the cursor {:onChange #(om/transact!...)}. Om.next, I'm under the impression that storing the input locally (om/update-state!) (om/get-state) and then transact'ing the contents of local state when user submits

tmorten20:01:17

I guess that was "one" of the styles of om.prev...I should say

futuro20:01:40

@tmorten: gotcha, thanks

futuro20:01:10

That's what made sense in my head, so I'm glad to hear about how other people are doing it

tmorten20:01:41

I've been doing the later with om.next, and according to the React docs, that leaves "two" sources of truth to the app-state...unless I'm reading it wrong (which is certainly possible)

futuro20:01:45

hmm...yeah, I could see that

tmorten20:01:30

The only way I know how to pre-load the initial values of a form is via getInitialState

tmorten20:01:51

then mutate the local state via onChange call

jlongster20:01:26

My query->sql compiler is coming along nicely. You can pull entities from a db now: https://gist.github.com/jlongster/df56f4f615ece93b8200

jlongster20:01:54

it ensures to always only generate a single SQL query to get everything

iwankaramazow20:01:33

Looks very promising

iwankaramazow20:01:19

One thing I have been wondering lately, what if we could put the SQL as co-located queries on components

dnolen20:01:05

@iwankaramazow: not going to happen in Om at least simple_smile

jlongster20:01:17

it'd require a whole different engine for tracking queries, etc

iwankaramazow20:01:30

the company where I work is heavily sql-based

iwankaramazow20:01:20

bringing datomic pull syntax, would be some form of treason

futuro20:01:47

@tmorten: based on that documentation, it looks like passing values from parent to child through params and storing that state is the anti-pattern,

futuro20:01:19

but I think locally storing state generated with the component itself isn't, as you've got one source of truth

futuro20:01:00

the component itself

dnolen20:01:33

@iwankaramazow: I’m sure that’s the case, but just not interested in that at all.

tmorten20:01:25

@futuro: I do see that. However, I essentially have a 1-1 map of local input fields in local state that are also in props. I was thinking that was where the problem is. Instead of just using those props to initialize the local state.

iwankaramazow20:01:59

@dnolen: it was more of a thought, not sure if a truly 1:1 client-server environment is desirable

tmorten20:01:22

And from what I can tell, it wouldn't make sense to have a (om/transact!)/mutate method on every input element's onChange event

futuro20:01:28

that seems excessive

futuro20:01:00

it seems like a better idea would be to sort out how to put the single source of truth for the life of the component inside it's local state, instead of spread across it's parent and local state

futuro20:01:31

that's my first thought, at least; your code might not bend so well to that

tmorten21:01:39

@futuro: agreed. That's why I think the way to do it is load up your components local state from props (getInitialState) and then when user commits the change via submit,etc, have a update mutate method to reflect that change in app state. That's how I am doing it and seems legit

nano22:01:27

Is there any way of setting the query params when creating a child component in the render function of the root component? Still working on routing, and while I can get the root query to fetch the correct parametrized data, I'm unable to parametrize the created child component, and thus it will not be able to use the data that was fetched for it. Thought I could just apply om/update-query from the root render function after creating it, but apparently it isn't a component at that point, or at least from that vantage point.

nano22:01:53

Ok.. figured out a workaround for that. Passing down the parameters to the child component via a computed prop and apply update-query! in componentWillMount.

tony.kay23:01:31

@drcode: Welcome. Glad to hear it

tony.kay23:01:18

@dnolen: You were asking earlier about a use-case for focus-query to be in the public API. We have one. We wrote a helper for lazy loading (e.g. (load-field this :comments)), and it extracts the ident and query from the component, uses focus to get the portion of the query that is interesting (the join on :comments in this case), and anchors the query on the ident.

dnolen23:01:58

@tony.kay: ok! PR to make it public welcome

tony.kay23:01:20

what exactly would you want modified? The doc string?

tony.kay23:01:29

I mean, it is already visible

dnolen23:01:32

or just documentation

dnolen23:01:36

I mean rather

dnolen23:01:42

in the wiki

dnolen23:01:13

anybody can do it really - but I’m fine with the official stance on it being

dnolen23:01:15

yes you can use it