This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-12-14
Channels
- # admin-announcements (283)
- # announcements (1)
- # aws (3)
- # beginners (24)
- # cider (32)
- # clara (13)
- # cljs-dev (1)
- # cljsjs (10)
- # cljsrn (24)
- # clojure (179)
- # clojure-dev (6)
- # clojure-russia (149)
- # clojurecup (5)
- # clojurescript (33)
- # cursive (23)
- # datomic (35)
- # devops (6)
- # emacs (1)
- # jobs-rus (11)
- # ldnclj (77)
- # lein-figwheel (1)
- # luminus (3)
- # off-topic (3)
- # om (179)
- # onyx (13)
- # proton (6)
- # reagent (60)
- # testing (1)
has anyone gotten a list view working in om next with react native on ios?
maybe i’m just not applying the right styles
@a.espolov: Use parameterized queries and Om will automatically pass them to both client and server-side read via the third argument.
@dnolen: oke, so selmer is not used often by clojure people which do web development ?
@roelof I think you should be able to render selmer template and then mount om app on one of the DOM elements. If you want to write your om components markup in selmer I don't see how it's possible. I didn't use selmer myself, though.
as @jetmind said if it’s a templating thing then the story is really the same as any templating thing that isn’t React or React-like
oke, I think the most popular is hiccup but I do not like the way I have to make template inheritance work
Im looking for a nice one which I can use for a ecommerce shop. so a lot of html code is used on every page. And I think the whole project will be 10 - 20 pages
@roelof: you can use Selmer to render static part of your page on the server and then use Om only for dynamic bits. If you want to write a SPA using Om only, I guess you're limited to om's templating or sablono (hiccup-style react dom wrapper)
Thanks, That is what I had in mind . I do not want to write a SPA . I do not think a ecommerce site is handy with SPA and I have no expercience with building SPA.
is this a good one for a absolute beginner : https://github.com/omcljs/om/wiki/Quick-Start-(om.next) ?
if you’re new to Clojure(Script), React, Om - then you will have a pretty steep learning curve
Im a beginner with I think one month experience. Im new to React and Om . Never learned that
@roelof: you definitely want to examine React, you may also find that Reagent is a better stepping stone if you’re coming to grips with Clojure(Script) at the same time
I know , but on Reagent I have to use Hiccup and I find it not handy with the project I have on my mind
@dnolen: let me know what you think about https://clojurians.slack.com/archives/om/p1450038494006522
@anmonteiro: yes that's fine
does it bother you that there would be duplicated code?
not sure about creating a .cljc file with only dispatch
, but that might be cleaner
@anmonteiro: it does not bother me for something this trivial
got it
@dnolen: When doing a remote interaction, the remote parse is going to return a query. I'm trying to avoid a race condition. When is it appropriate to mark in the app state that you are going to fetch something? It is a pain in send, because you might need to mark several things "in progress" based on the query...but the remote parse code is supposed to be side-effect free. The race condition comes in when someone interacts with the UI while the query is in progress....you don't want the remote parse to see "not present" again, but instead "loading".
the easiest place is during the remote read phase, so OK to swap a marker during that?
I see no problem, but this seems like a formalism that needs to go in the "cookbook"
@jannis: "parameterized queries and Om" static om/IQuery (query [this] '[(:animals/list {:start ?start :end ?end})]) this it's ok example for remote read om.parser?
@a.espolov: Absolutely. The signature of the parser :read
function is [env key params]
, so on both client and server side params
will be {:start <val> :end <val>}
in this case.
@a.espolov: Are you sure the query is sent to the server and parsed from the HTTP/WS request there correctly?
@a.espolov: That's odd. Can you post your query, your client's read
function, the send
function, the server read
function and the output of (clojure.pprint/pprint env)
+ (println key)
+ (println params)
on the server side in a gist?
@a.espolov: What does your query look like exactly? It's not '[(:animals/list {:start ?start :end ?end})]
for sure 😉
I have not one thing is clear whether you can use a nested structure QueryParams? static om / IQueryParams (params [this] {: xyz {:sort-key :abc :sort-type :desc })?
You write :inspection.list/outlet {... param map...}
where it should be (:inspection.list/outlet {... param map...})
The way you're doing it is that :inspection.list/outlet
and the param map are treated as two separate sub-queries. Even worse, maps in queries are considered joins, so Om thinks the params are a query for the keys :paging
, :filters
etc.
If this is unclear, read up on the query syntax on https://github.com/omcljs/om/blob/master/src/main/om/next/impl/parser.cljc#L5 and look at the documentation in the wiki. https://github.com/awkay/om-tutorial might also help.
I'm having a little trouble with Union queries
my query is of the type [:foo {:bar [:some/key] :baz [:other/key]}]
though it seems Om is treating the union as a join, and only parsing the :bar
part
looking for some pointers on what /where to look for
@anmonteiro: Hmmm... I might be wrong but the syntax for unions and joins is ambiguous, at least according to the parser docs. So not sure.
I've checked the grammar
it looks that my query matches it
at least I believe so 😛
Judging from https://github.com/omcljs/om/blob/master/src/main/om/next/impl/parser.cljc#L83 [:some/key]
should be a map.
you're right
seems like a bug
because it doesn't make sense
I think it should be a join when there is just one key/value pair and a union when there's more?
does my query look wrong according to the grammar?
doesn't it depends on the "level" that you are? for example, at root it's union, at property level is a join
would appreciate @dnolen 's input
@anmonteiro: wouldn't you have to put an name before adding your union? like: [:foo {:name {:bar [:some/key] :baz [:other/key]}}]
@wilkerlucio: yes according to the code, no according to the grammar
or at least it seems so
Yeah, I think so too. The root of the query is a vector of query expressions, and those can be keywords, idents, param expressions, joins and unions. And both joins and unions can be EdnMap(Keyword, QueryRoot).
maybe the grammar should change to accept unions only at root and join levels?
Unless... unions have to be at the root of a component query and that's just not part of the grammar.
not sure if it's a docs problem or a bug, I can understand if it needs to be as @wilkerlucio says
unions can definitely be at the root level
the tutorial shows this https://github.com/omcljs/om/wiki/Queries-With-Unions
in DashboardItem
's query
there it adds a name for it, this is the kind that I mean for "join level"
Yeah, in that example it's not the root query, it's a subquery that's joined into the root query.
right, but it's at the root of DashboardItem
`
it's what I meant
I don't understand the parser code well enough, so I can only guess. @dnolen to the rescue? 😉
I haven't read through it too
@anmonteiro: on your example, [:foo {:bar [:some/key] :baz [:other/key]}]
I can't see how you would get he value of your union, which name it would have on the return?
it looks more like two joins instead of an union, is that correct?
I was going to have parse keys for :bar
and :baz
@wilkerlucio: it looks that you might be right
so the docs might need to reflect it, but we'll only be sure when David gets summoned 😉
he eventually will
So UnionExpr in this line here is wrong? https://github.com/omcljs/om/blob/master/src/main/om/next/impl/parser.cljc#L16
that clears things up
thx a bunch
so I've been writing some routing experiments
and at this point I believe that using unions to perform routing in an app that does some form of remoting might not be ideal
because the parser will always attempt to read every key present in the union query
so either 1) we incur in a lot of remote requests everytime we re-render (will read every key of every route) 2) we have to write a lot of unnecessary code to prevent 1)
the approach that's suiting me best atm is using set-query!
to the current route's component query
would love to hear people's opinions on this
You can prevent the extra requests by only getting the remote query for one sub-branch of the union in the read for the union, but it does take more code. I like using a union so you can see the entire demand (unioned across pages) in a single query. Currently though, you have to write a lot of custom code to re-rwrite your queries in your send function if you don’t want your server to know about your routing machinery. I’ve talked with @tony.kay a bit about this; currently process-roots
doesn’t traverse union queries but if it did it would go a ways to help solve this issue imo. I’ve personally been trying to avoid using set-query!
, but thats how I initially tried to tackle this problem. When using set-query!
I had to write extra code to construct a query that could be used to normalize data across my app since at any given time the root query might only have enough information to normalize the data for the current page.
It is perfectly legal to switch out a join via a query param from IQueryParams (e.g. compose in a different components query via set-query). So, instead of stating "it could be one of these, detect it via state", I just end up with "it is exactly this" in the query, which works nicely with process roots.
I guess what I don’t like about it is that it forces me to move state out of my state atom and into the component instance whose query is changing
@tony.kay: exactly how I'm tackling the issue
@noonian: I abstracted that into helper functions. The component can call set-query and pass something generated from helpers.
I've taken a slightly different approach to routing recently: Use bidi to translate from URLs to mutations (when loading a page) and from app state to URLs (e.g. when selecting something). Almost all routing stays out of Om and Om simply has an app state that it renders.
https://github.com/Jannis/custard/blob/master/src/web/routing.cljs (`navigate-to` is called whenever the page is loaded or the URL changes, activate-route
is called by my App component to change the URL and trigger the necessary mutations to get to the desired state): https://github.com/Jannis/custard/blob/master/src/web/app.cljs
given a route description use the anonymous ui
macro to generate the needed route classes with union query bits
@jannis: I do a similar thing, do you just use a static query for the entire application then? what about remote reads?
Yeah, I’ve been using bidi so that I can use the routes in the server to render the index for exactly the routes that the client needs.
@noonian: Nope, parameterized. That app there serves versioned data from Git, so the query is parameterized by commit, more or less. Remote reads are done on page load and the rest is done via sente push notifications from server to client (e.g. when there's a new commit or working directory changes) that then trigger refetching the current "commit" remotely. And it reads remotely whenever you change the "commit" (or branch or tag) you're viewing. It doesn't do lazy querying for views/routes.
the ui
approach David mentioned seems like something to try
not sure I understood it entirely though
I like the anonymous ui
approach. I think its basically an iteration of the union approach though, so will need to solve the problems with remotes for unions before going down that route I think.
@dnolen: whenever you have time I'd love to hear some more details
@noonian, @tony.kay When using unions for routing, is it possible to change the union dynamically at runtime (via set-query!)? I think of all the code behind those routes as possible candidates to put into a Google Closure module to optimize the build. I'm worried that when referencing components from those routes, the code motion gets prevented and a lot of code lands in the base module instead of the route module.
@r0man: I haven’t done anything using code motion. But I think if you write the parsing code to just use the provided union query it encounters, and figure out what to union on by some function of the app state, then you won’t need to statically reference the actual components used to build the query and could probably use it in conjunction with set-query!
.
But you will run into the same problems of building the correct query to use when trying to normalize data I think.
@dnolen: I'm guessing there is no way to pause the queue processing in the reconciler?
When you use sente to communicate with the backend. It may not be ready right away though, so you have to queue pending queries in :send
, using a channel perhaps. Or the reconciler could provide a way to prevent queues from being processed until a condition is true?
in general you do have to be explicit when you want something to go into some specific module
This probably isn't limited to sente. Any backend that you have to wait for to become available for comms.
@noonian, @dnolen: I played a bit around with code motion and sometimes I ended up with empty files when not beeing careful. Like referencing symbols from those route modules. I'm using om/add-root!
at the moment to swap components out at route changes. Not sure exactly if this is a good solution or not 😕
@r0man: that was my first approach to routing
it's how we did things in Om (Now) world, so I firstly tried that way
it might represent a problem with normalization
Have you noticed much of an improvement in code size when it works? I kind of assumed most of the code supporting my app was cljs, om, and react.
switching root when the route changes is definitely a simple approach
it didn't play out for me because I ended up having to repeat a lot of code
@noonian: when code motion worked I had a JS file for each route. I have 10 modules each between 5k and 21k of size. There isn't much code yet for each route yet, but I think it adds up. I think not having to load all view code on the initial app load is desireable.
I am struggling a bit with merging the data returned from remote. It is in the form: {:list [{:a 1}]}
which matches a top-levle key. Do I need to define a ‘merge-tree’ function to merge it into the local state?
@monjohn: depends on what you're trying to do. If you want to replace all the local data for :list
key with what server returns, you can use default merge-tree
, which is just plain merge
of top level keys.
If you need to do some smarter merge, you should supply your own implementation of merge-tree
I noticed that I can call (om/params MyComponent)
, but (om/get-params MyComponent)
returns #object[Error Error: Assert failed: (component? c)]
. Is om/params
something I should not be using?