This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-12-02
Channels
- # admin-announcements (29)
- # aws (11)
- # beginners (247)
- # boot (11)
- # business (1)
- # cider (73)
- # clara (5)
- # cljs-dev (37)
- # cljsrn (29)
- # clojure (86)
- # clojure-dev (9)
- # clojure-indonesia (1)
- # clojure-italy (3)
- # clojure-nl (1)
- # clojure-russia (195)
- # clojure-sg (2)
- # clojure-uk (3)
- # clojurecup (1)
- # clojurescript (296)
- # clojurex (2)
- # code-reviews (6)
- # core-async (3)
- # cursive (33)
- # datavis (9)
- # datomic (11)
- # funcool (31)
- # hoplon (1)
- # ldnclj (8)
- # lein-figwheel (5)
- # leiningen (5)
- # luminus (4)
- # off-topic (3)
- # om (172)
- # onyx (13)
- # re-frame (5)
- # reagent (84)
Oh... I just realize something.
How would I go about implementing a form that has one single submission button, but submits multiple items which have the same format. An example would be like shopping cart
Should I do deftype
?
it appears support for :notify-command
was explicitly removed from figwheel some time back. is there a way to restore or replace it?
@trancehime: what's wrong with a vector? As in {:items [{:name "top" :quantity 1} {:name "kek" :quantity 2}]}
I was asking about that over at #C0620C0C8
I had figured I would just use a vector and store that vector in an atom
but I do have some default values that are being rendered into the view already as a vector of items
but then my question became, would I just pass that entire atom containing the vector
into a function which processes the data
Yeah, just plain reagent
I'm not using re-frame or anything
(I might consider into using re-frame in a different app or something)
So yeah, I would keep the state in one or more atoms, and dereference them when you need the value inside.
well thing is
the default values for a form come from a database
so i planned to write some call to server (AJAX probably since that's simple and easy for me to do), populate the atom, then render after the atom has been populated.
i guess I could just write the atom as global and continuously just reset!
it when the form data has changed
and then I just dereference the entire atom (since I want to pass the entire vector) to my function?
oh dangit that's what I already do for a different component
I am mega dumb
@cjmurphy: i do (fn [response] (reset! atom response))
as my handler
cause i am using cljs-ajax
not that one
cljs-ajax
and of course I implement handler and error-handler
just meant that in the callback I would reset!
that globally defined atom
with the data retrieved from the database,
so every time the database is queried, in the callback I would just change the value in the atom to the new one retrieved from the db.
when the component is to be rendered/loaded
idk, enlighten me if there is a better way to do it
Oh no of course I would not do it in the inner fn
OK, well, TIL the correct term is on mount
we have cleared this up
You can refer here for lifecycle events if you ever need to - https://facebook.github.io/react/docs/component-specs.html#lifecycle-methods
oh it's for a whole page, essentially.
I wasn't entirely being truthful with calling it a cart, it's not really a cart, but it was the closest example to the thing I have in mind
It's usually just best to use the exact example, unless it is indeed top secret, sometimes people might understand things differently in analogy. But then again, they might as well in the same example, soo...
It kind of reminds me of a project I had to write for the university, I did it the dumb way as well - AJAX calls, atoms per view namespace, resetting them and so on.
Well, maybe this would be a better explanation for what I am trying to accomplish
I have a page where the user would input some data for statistics of a competitive game. Let me use example of basketball, which generally has 13 players per team, total of 26 players. For simplicity's sake, let's say the user just has to input 3 things: POS, MIN and PTS. What I would get from the database would be the players who would be playing in the game, with POS, MIN and PTS set to default values.
Once this is all displayed on the page, user would fill in POS, MIN and PTS as needed, and then send the now changed values back to the server (basically, I do some server-side processing with this newly filled out data)
How come server already knows the lineup for the match, isn't that something user decides as well?
what the server knows is based on game schedule, for games that havent actually been played yet. People know which teams will be in the game, but because the game hasn't actually played yet, we don't know how long each player was in the game (MIN), if they were on the field when the game was actually finished (POS) and how many points they scored for the team (PTS)
basically, a really dumbed down version of populating BOX SCORE
That is alright, but is it clearer now what I'm trying to accomplish?
Would the approach we discussed prior be acceptable as well, or would there be a better approach to handle this?
(In my actual case, there would be less than 26 players, realsitically the most would be 10)
(sometimes there would only be 2)
Catch this instead - https://gist.github.com/jaen/dd22b3432581fc7ab8f5
map-indexed
takes each item in the coll and apply the (fn [...])
stuff until the coll is exhausted, right?
in the callback of get-game
you reset the game-state
atom to initial values, in the callback of update-game!
you can display failure/success and/or close this form if it's no longer needed.
you just dereference it, right?
yeah, that's what I did with my other thing, I just dereferenced the current values in the atom
Ah, I assumed you passed the atom from your phrasing, maybe I've just misunderstood you.
ah not the literal atom, but more like, passing in the dereferenced thing in its entirety.
which should be the collection.
anyway, I'm assuming swap! game-state update-in [idx] assoc :key new-value
means we are updating the element in the index of game-state
by assoc
a particular key (in your gist it's :min
) with the new-value
right? where [idx]
would be referring to {stuff}
or rather, the {stuff}
at index idx
Then it all makes sense; now that I scrolled up I'm not sure why I though you were passing that atom, my bad.
of the collection, which is game-state
yeah, whoops
(i have learned a metric ton of stuff from you about this, so thanks so much)
(swap! game-state (fn [old-value]
(update-in old-value [idx] assoc :min new-value)))
which in turn is equivalent to
(swap! game-state (fn [old-value]
(update-in old-value [idx] (fn [old-value]
(assoc old-value :min new-value)))))
oh jesus that looks convoluted
You could also have written it as (swap! game-state update-in [idx :min] (identity new-value))
if I'm not mistaken; do you see why?
constantly
always returns the same value... which is new-value
, regardless of how many args you pass into it, if I'm not mistaken?
So I can then delegate the assoc back to the key vector of update-in
and just use that as my update function.
As for nesting - well yeah functions like swap!
, update`, update-in`, alter-var-root
and so on accept a function that maps from the current state to the new state, so if you nest them, like in the case of using update-in
to change something inside an atom with a swap!
it can get unwieldy fast.
So there's the sugar when you can explode the function into the body of them, as long as it's reasonably simple (which it is in this case)
It takes a while to get used to that, at first it trips you up constantly how that works
so in this example, game-state
is the atom, update-in [idx] assoc :min new-value
could be exploded into the function portion.
update-in
in of itself also needs a function as an argument.
Yeah, I actually see it now
And usually there's little reason to put more complex logic inside the update rather than the outside.
in the exploded version, old-value
would be the old element at the index of the atom game-state
and we are simply just assoc
the new value of the key to that old element ;o
I think?
and old-value
in the inner function is the element at the index?
Yeah, they had the same name so I got tripped up lol
Much easier to understand the logic, but of course not very pleasant to look at haha
Well that's why we call it syntactic sugar?
Is the ability to close over the old value in the enclosing fn. If for some reason your value in update-in
would depend on the old value in swap!
, you couldn't do that with the sugar
Well fortunately in this case I don't need to care exactly, since I'm just dealing with replacing values and not doing any computation or processing that would for some reason require the old value
I guess as you said, it could be a possibility in the future. I guess I can worry about that bridge when I have to cross it
Well, since Clojurescript is single threaded (because JS is of course) you could cheat by just derefing the atom again, but that won't work in Clojure - in a multithreaded environment you're only guaranteed to get a consistent value if you use the one you get as the argument to update function.
omg, just talked to my supervisor...
turns out i might not even need websockets after all
Well, I remember you mentioning something about chat, so I don't imagine how to better do that than websockets.
@jaen: Hmm, it's not exactly a toy project.
Just curious, maybe there's a legitimate reason, but wonder what would that be for an interactive chat
You know the thing about the data input I just asked you about
It's supposed to be done in a way that n
amount of users are allowed to input statistics for the same match
I thought it had to be done in a live format
Turns out I don't need to care about synchronicity, as users will choose to apply to a schedule they wish to input data on ahead of time
I was only concerned about channels not the messages :V
Well, I just implicitly assumed you're in fact writing a chat, where websockets are the best solution. Otherwise I might've suggested websockets are overkill P ;
@jaen yeah, I did. In case I do actually end up needing it
hellow
In a figwheel project, how do you you interactively (browser) test an :optimization :advanced build? "lein ring server"?
but usually you'd just need to configure the ring server to call the handler that figwheel uses
Figwheel takes care of everything. Except when it does not work. Using :optimization :advanced is my case.
"lein ring server" will probably do in 99% of the cases then. Except when it does not work. Such as when you have websocket handelers. 😉
Really silly question, but I’m trying to get Ladda (a button library) to work with Reagent, but it’s giving me headaches. The JavaScript equivalent is
var l = Ladda.create( document.querySelector( '.my-button' ) );
Which I translated to
el (fn [] (.getElementById js/document id))
ladda-load! (fn [_] (.create js/Ladda (el)))
in the component-did-mount, but it seems not to workgiving “a is not a constructor”
@joelkuiper: one is using getElementById
the other is querySelector
?
nah it was a bug in the Ladda library, apparently the order of dependencies matters 😕
hard to track without source maps 😛
so I made a bit of progress, not a lot; but some 😛
might be enough reason to generate a proper cljsjs from this
@dnolen: I got it. I am working on gorilla-repl and https://github.com/JonyEpsilon/gorilla-repl/blob/develop/resources/gorilla-repl-client/js/repl-ws.js
so if you attempt to call anything at all of your code, it will never have the name you expect it to
@thheller: Exactly. And the JS I was pointing to needs a ws-service. That's why "lein run ..." is my only option and "lein ring server" won't work.
so you could probably roll your own main function that just starts a httpkit server with the gorilla handler
@thheller: with "lein figwheel" and :none, there is nothing to worry about. Works straight out of the box.
@deas: you always should exclude any dev time stuff from your build that is not compatible with :advanced
compilation
Speaking of excluding dev stuff, how does everyone here deal with doing that? specifically in html templates? I have a user.js file that I want to keep out of my production build, and I end up rendering the template server side to conditionally include it in dev mode. Is there a better way that I might be missing?
@deas I didn’t say it was, it was just that your comment above didn’t make any sense to me
so all you really want is a server than can work for gorilla repl that isn't figwheel
https://github.com/JonyEpsilon/gorilla-repl/blob/develop/src/gorilla_repl/core.clj#L30
@dnolen: Sorry about not being clear enough. In fact I was just wondering "How do I interactively try :advanced code" in the browser.
@dnolen: What are a couple of other ideas? I don't mind my solution, but I'm always looking for simpler ones.
@jstew you can do this by using different builds. the builds can define different entry points.
so your prod build just loads the main namespace, but the dev build uses a dev namespace that loads your tooling + the main namespace
so I just configure figwheel to use the dev build, then lein cljsbuild
the production build? Seems so easy that I'm kind of mad at myself for not thinking of it!
Is it possible to inline Node dependencies into the compiled output file so you don’t have to install NPM dependencies to run it?
Hi, i'm trying to get a file via http request and convert it to dataURI with this code but it doesn't work, any idea? (def data (atom "")) (go (let [res (a/<! (http/get "http://files.parsetfss.com/42a74b87-d8af-4d8b-9bec-be3039f672fe/tfss-247d838f-26c4-4a0e-89b1-793f5165799b-0.jpg" {:with-credentials? false}))] (reset! data (str "data:" (get-in res [:headers "content-type"]) ";base64," (js/btoa (:body res))))))
i’ve got this error : Uncaught InvalidCharacterError: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.
`function utf8_to_b64(str) { return window.btoa(unescape(encodeURIComponent(str))); } `
but it doesn’t work, i no longer have the InvalidCharacterError but it doesn’t display in the browser
(go (let [res (async/<! (http/get "" {:with-credentials? false}))]
(prn (js/btoa (js/unescape (js/encodeURIComponent (:body res)))) (get-in res [:headers "content-type"]))
(reset! data (str "data:" (get-in res [:headers "content-type"]) ";base64," (js/btoa (js/unescape (js/encodeURIComponent (:body res))))))))
@dnolen in js bin running (range 0 10) throws and Invalid number format error, analogous to what was happening in https://github.com/mfikes/replete/issues/8
@mahinshaw: I don’t know or care about bugs in jsbin