This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-04-18
Channels
- # admin-announcements (3)
- # arachne (8)
- # beginners (55)
- # boot (51)
- # cbus (1)
- # cider (15)
- # cljs-dev (5)
- # cljsrn (8)
- # clojure (203)
- # clojure-austin (2)
- # clojure-belgium (12)
- # clojure-boston (6)
- # clojure-czech (47)
- # clojure-dusseldorf (14)
- # clojure-estonia (1)
- # clojure-greece (42)
- # clojure-japan (2)
- # clojure-poland (4)
- # clojure-russia (97)
- # clojure-sg (5)
- # clojure-uk (41)
- # clojurescript (122)
- # code-reviews (4)
- # component (3)
- # core-matrix (19)
- # cursive (25)
- # datomic (16)
- # devcards (24)
- # editors (6)
- # euroclojure (1)
- # hoplon (88)
- # immutant (3)
- # incanter (4)
- # jobs (5)
- # keechma (1)
- # luminus (1)
- # om (44)
- # onyx (22)
- # parinfer (3)
- # planck (1)
- # proton (3)
- # re-frame (5)
- # reagent (30)
- # ring (2)
- # spacemacs (1)
- # untangled (92)
- # yada (1)
hey all, I have a need to use :ui/... attribute on my root component, and that means I have to specify ident for this root component, so I set up something like this on my Root:
static om/Ident
(ident [this props] [:root :main])
Shouldn't that mean that map value that I pass to :initial-state will be auto-converted to db state that starts with: {:root {:main ....}} ?
After that I tried setting explicitly my own db state by wrapping my map in atom, and manually of course rewritten the map to start with {:root {:main...}} but it still didn't get proper value in render props
@vmarcinko: you only have to specify an ident on components using ui/…
attributes if you want to use the helper functions in untangled.client.mutations
. you can write your own mutations that add those keywords to the top level of your app-state, and then query for them from the root component
it doesn’t make sense to have an ident on the root component. What would it’s join point be? In your example, you assign the ident [:root :main]
, so there would have to be a component above root that queried for [:some-key]
, where the app state looked like {:some-key [:root :main]}
in which case, the component with :some-key
would be the root component. kind of a proof by contradiction in that sense (that the root component can’t have an ident), since we started out by assuming that the component with the [:root :main]
ident was the root component
@vmarcinko: Yeah, the root component is a bit tricky. It is easy enough just to nest things down one level and treat root as a special case. It shouldn't be a problem to give Root an ident and normalize it, though....it is just one more level of indirection. What did your state look like? I've honestly not tried.
I've started a Cookbook project: https://github.com/untangled-web/untangled-cookbook It has a template and a script for creating new recipes. It is mostly empty at the moment (just ideas written down and one recipe mostly written). I'm going to try to add a few a week. If anyone has an idea of how to track interest in specific recipes I'll be glad to write those first.
I am going to be a bit strict about content. Trying to maintain a level of consistency and quality. I'll post guidelines soon.
@tony.kay: would you need a custom read to treat the normalized root as a special case? or is there a way to do it with the built-in read?
@ethangracer: @tony.kay Yes Ethan, I tried to use your set-string! mutation function within root component, and it complained about root having to have ident, so I also was a bit baffled by root comp idents...As you said, I even assumed that I would have to introduce new root component, that would be on top of exsting one due to this path issues
So, that's why I asked here to see if I don't udnerstand something here, or none yet tried to put ident on root, as it seems is the case
Actually, I still am not sure is it normal to use set-string! at :onChange handler for form's text field which I'm trying to do now, and I started by using set-string! Although it doesn't look so nice to me to see logs about transact! being called on each key pressed inside text field
but as I udnerstood, as complete om/untangled noob, that if I use component local state, then text field's value isn't visible in app state, and support viewer will not be able to reflect changes insdie these text fields
@vmarcinko: ah, gotcha. it sounds like you understand it to me, I haven't been successful getting an app-state to normalize in any reasonable way with a root component ident, though I haven’t given a concerted effort in awhile. as far as what defines 'normal' patterns, we’re still very much in the process of defining it. very open to feedback on what others think are good approaches. you are correct though, component local state is not currently recognized by the support viewer
if you’re wanting to mitigate the logging clutter for set-string!, we found debouncing to work well — still a fair number of logs, but significantly fewer than one per character
@ethangracer: debouncing?
haha, no worries, me too! web development is very new for me
it’s a timeout on a field, so the onChange handler doesn’t trigger for every onChange, but only after the user hasn’t entered something for awhile
(defn debounce
([f] (debounce f 1000))
([f timeout]
(let [id (atom nil)]
(fn [evt]
(if (not (nil? @id))
(js/clearTimeout @id))
(reset! id (js/setTimeout
(partial f evt)
timeout))))))
and then we use it on a text-field like so (debounce #(onChange (-> % .-target .-value)))
@vmarcinko: I'll do a specific test soon on putting an ident on Root...I cannot think of why that would be a problem...just generates an extra edge in the graph, but I have never tried it...so there is possibly something I'm missing.
Is there a way to passed om/computed
data to the root? I'm writing a devcards using @tony.kay's untangled-app
macro but the component I'm passing to untangled-app
expects computed data.
offset by one...make root just be a non-ui concern that is about rendering your real root
In general, just treat Root as a special case that has a single top-level div for the react-key and locale...and push everything else down a level
yeah that's what i had in mind, just wanted to make sure there wasn't a cleaner way
makes sense, thanks!
@tony.kay: I have a use case in mind that I'm pretty stuck. How do we deal with different params being set on a component and on a class path. The use case is : I have a root and and active component which will be swapped later when I change route. When I change route I do initial set-query so the whole root would be reindex, at this point the query in set-query is the default one ( which is not the valid one to be sent to server ). Then when the new active component mounted, I set-query on this component ( now this makes thing complicated ), this is the right query and will be sent to server. The problem is, when the result come back from server, it get reread through nested query from root, and therefore we got the unvalid params in the read function. This is annoyed because I do check the params to determine that I should return the correct results or not ( prevent staled data ). How do you deal with this nested read, component swap in untangled ? I'm tempted to use untangled but I would like to understand om next well first. Thanks
use unions. See the untangled-demo app on my awkay repo from my most recent talks...it shows switching in/out things....the cookbook also has an example, but I'm not done with it yet
I don't have time to read your entire question...sorry, very busy day...so I realize that isn't a great answer 😉
Antonio on #C06DT2YSY can tell you more about the weaknesses and such of dynamic queries...Untangled simply does not support parameters on props or joins at all...so if you're trying to do that, it won't work...I can talk about workarounds, but not today
see my two recent talks...the one in PDX I go over this in detail (what to do instead of parameters)
nice, it's good to know. I have a really hard time working with parameters, it's just not right
nice idea...but D.N. is exploring ideas to prove them out...not all of them will work out
hey all, looking for some feedback for those who are interested (@currentoor, @cjmurphy, any others?). we are in the process of improving / completing the error handling story. the initial idea is to have a global error in the app state keyed at :untangled/server-error
, which is set by the networking object’s send function when it receives an error. we would provide a hook point when creating a new untangled client to provide a mutation symbol that could be used to define (optionally) a global error handler. you could also provide a mutation symbol to the load-data
functions to handle failed reads, and the currently implemented tx/fallback
mutations would be used for mutations.
so the order of execution would be:
1) server sends an error to the client (status code, message, body)
2) client saves the error to the untangled/server-error
key at the top level of app state
3) global error handler defined as a parameter to new-untangled-client
is called
4) error handler specific to read or mutation that failed on the server is called
there would not be a default implementation of error fallbacks, so if the user doesn’t clear the error from the app state, it will stay there until another error overwrites it. so the user could have the option to query for the error anywhere in the UI using a link and determine what to show / what not to show based on that error
@ethangracer: so far we just added our own error event listener to the xhr-io object inside untangled client, that worked for us.
In the case of a failure, would both the global error handler be called and the mutation specified in tx/fallback
?
@currentoor: we haven’t decided on that yet, that was one of the remaining big questions
I think it makes sense both ways for different reasons
the global error handler is meant to be global, so shouldn’t it be called every time? then again, fallback mutations could be meant to override it
really just a design choice
and, what makes sense for the people who are using it
To me, a global error handler is only useful for a limited one or two cases, unauthorized or unauthenticated. Other errors IMO are mutation specific. So I think it's fine for global error handler to alway execute.
global error handler in our case just does stuff for 401 or 403, it would be nice if the error status is not either one of these then global handler warns us that there does not exist a tx/fallback
(if one does not exist for this mutation)
thanks for asking!
Hey guys, good job with the untangled project. I'm following the project since the public release and can't wait to see more. @ethangracer the error handling sounds good for me. But I have to think more about the global error handler idea. I dunno if it's the right choice. @tony.kay the cookbook is a great idea. Here is the wish list. * Server-side security for UI-generated queries * Generate a new entity (UI/Server) * Paginate through a very large list of items * Push live data updates from the server with Sente
@currentoor: right, it’s nice to have something that catches certain kinds of errors from any mutation, AND errors that are triggered only by certain ones. so something like todo/new-item
might return a 403 if the user isn’t authorized, and that would be handled by the global handler, whereas if the actual action of adding a new item failed, then the transaction specific callback would clean that up
and there’s no need to put the 403 logic in every fallback
i’m with you, thanks for the input!
@baris: let me know if you have more thoughts
going to be working on this for the next day or two
@ethangracer: could not have said it better myself
Is there a way to access the queue of remove mutations? If my first request failed, I want to undo my app-state and flush the subsequent mutations?
@baris: I added your list to the Wiki. Anyone else: Please vote there: https://github.com/untangled-web/untangled-cookbook/wiki
@tony.kay: thanks. Is it possible to extend ur recipes list? I'd like to have a full multi form CRUD example. With basic form fields like, textfield, textarea, date picker, checkbox, combobox, file upload. I'd be glad if I can help.
sure...the wiki is editable by anyone, so add it to the list there, and put your uname after it...hopefully others will vote. If you want to write it, even better. There is a script in the repo (new-recipe) that will create a starting template for you and add a bullet item to the README...just run it:
./new-recipe form-wizard "Wizard-like form filling"
or something similar
Not sure how to edit that wiki so I cloned it locally, but got this when I tried to push:
Failed with error: fatal: unable to access ' ': The requested URL returned error: 403
on the wiki itself...if you are signed into github you should see a "Edit" button (gray)
@tony.kay: about the conversation we had before, you were right, I was able to use the global state for it, thank you