This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-01-25
Channels
- # aatree (3)
- # admin-announcements (14)
- # aws (2)
- # beginners (23)
- # boot (58)
- # braid-chat (15)
- # cider (8)
- # clara (5)
- # cljs-dev (1)
- # cljsrn (38)
- # clojure (82)
- # clojure-china (2)
- # clojure-czech (16)
- # clojure-dev (11)
- # clojure-finland (1)
- # clojure-ireland (6)
- # clojure-japan (3)
- # clojure-portugal (1)
- # clojure-russia (152)
- # clojure-sg (7)
- # clojurebridge (3)
- # clojurescript (86)
- # code-reviews (3)
- # core-matrix (4)
- # cursive (25)
- # data-science (1)
- # datascript (2)
- # datavis (98)
- # datomic (21)
- # dirac (97)
- # emacs (1)
- # hoplon (1)
- # jobs (2)
- # ldnclj (21)
- # off-topic (3)
- # om (204)
- # pedestal (3)
- # proton (12)
- # reagent (125)
- # ring-swagger (9)
- # slackpocalypse (1)
- # spacemacs (1)
- # vim (1)
- # yada (19)
@gadfly361: When using semantic-ui’s widgets with javascript, if I don’t care about cljs purity, I can include the jquery and semantic-ui.js dependencies, then run i.e. $(‘#select’).dropdown() in the console to initialise it. How can I call this from within my cljs source files? Or how do you use the semantic ui widgets currently? Not sure of the right way to approach this.
Ah figured it out. For posterity’s sake,
$(‘#select’).dropdown()
is equivalent to (. (js/jQuery “#select") (dropdown []))
. I don’t know if this is a sane way to do it or not, but I just called that in the componentDidMount function, and it works.@sooheon: Yeah, that's how you would do it, more or less. Though consider what if you have, say, two components like that, what then?
Here's an example I posted before of using exactly the dropdown - https://clojurians.slack.com/files/jaen/F0JKFP7T6/-.clj
Might be helpful, especially the part about reagent/dom-node
instead of jQuery selectors.
If you would need it during rendering there's also reagent/current-component
, but this should be rather rare, I think.
Just calling .dropdown with no args works for me, could you explain the rationale behind #js {:match “text" :onChange (fn [new-value] (reset! value new-value))}
please?
match
is an option on what the dropdown should filter when you enter values - it can be "both" (default), "value" or "text". I want to match on text only.
onChange
is a callback that's made when value changes. The fact, that the dropdown "appears" to work is not enough - you have to somehow have your Clojurescript state synced with the dropdown and vice-versa.
(fn [new-value] (reset! value new-value))
synchronises the current state of the dropdown with an atom passed as an argument.
The code in :component-did-update
does the reverse - it updates the dropdown when the atom changes.
That's all because it's a stateful JS component, so you need to push and prod it a bit to behave with reagent.
I trust you've seen this example here - http://semantic-ui.com/introduction/integrations.html#managing-lifecycle?
Yeah, but that's for literals only. #js name
won't work, you need something like (clj->js name)
, though I usually prefer to construct options as literals most of the time anyway.
@sooheon: yeah, actual textual {:a 1}
or 2
or "string"
or something, not a function returning those.
@jaen: Awesome :). I’m still not quite used to the arg destructuring—is the choices
atom to be passed in supposed to hold a vector of maps with {:value foo :text bar}?
Also I see that you did :as options
in the destructuring but never used it—what would you use it for?
The downside is you can't change the list of things once you instantiate the component, but I didn't need it so far.
As for :as options
it's really just my preference. I feel it documents what I'm destructuring. No need to actually do that if you feel it's superfluous.
Also, you could probably use hiccup vectors in the choices map - I didn't try it yet, but I see no reason for it not to work.
Also another downside - string keys; it's a JS library, so any key will be stringified. I could probably add some code to map that both ways, but didn't have a need to yet.
I would probably still rewrite them into React at some point (a la what re-com did with chosen dropdown for example), but if you're prototyping then it's perfect.
@jaen: I still don’t think i’m understanding what shape to pass it args in properly, I’m getting the “children with the same key” error, so value
isn’t getting bound correctly. Is it supposed to receive two maps, one: {:value (r/atom nil)}
representing the value of the dropdown component, and then other other {“foo” “Foo” “bar” “Bar”}
representing the choices?
(let [users (sc/users-query)]
[dropdown {:value user}
(for [user @users]
{:value (:id user) :text (:username user)})])
[{:keys [value] :as options} choices]
doesnt this mean you take one thing called choices
, then destructure it?
Ahhhh I see. Yeah, in the argument vector each top level sexp should be its own argument, I was confused by let where I’m binding something to a destructured map :)
Yeah. Argument vector is an ordered vector of patterns you would bind your n-th positional argument to.
@jaen: one more thing! :) in your actual example, you pass {:value user}
as first arg before you iterate over @users
as user
below. So the user
below is a map that contains :id
and :username
keys, what is user
above that is the val of :value?
(defn user-choice-component []
(let [user (reagent-utils/wrap
#(:id @selected-user)
#(reset! selected-user-id (js/parseInt %)))]
(fn []
(let [users (sc/users-query)]
[dropdown {:value user}
(for [user @users]
{:value (:id user) :text (:username user)})]))))
Where reagent-utils/wrap
is this thing I've done - https://gist.github.com/jaen/c59a3e0abcf0c6f6ade2
But the stock reagent wrap
has this problem it receives a value, so you can't for example construct it in the outer let
of a Form2 component
Before writing that wrapper I actuall had a second parameter in options
, the :on-change
callback
i thought the :value val was just an atom that held something like component local state
Why I'm doing it that way, is because I need a "view" of another reactive value that's updateable through that "view".
It's a bit like the wrap
example here - http://reagent-project.github.io/news/news050.html - but like I said, you can't really use reagent's wrap
in an outer let of Form 2.
So, to sum up
(defn user-choice-component []
(let [user-id (reagent/atom "first")]
(fn []
(let [users (sc/users-query)]
[dropdown {:value user-id}
(for [user @users]
{:value (:id user) :text (:username user)})]))))
Thanks for all the reading material though. I’ll try to start absorbing it through osmosis
Also, if anyone thinks I'm doing something dumb with my Wrapper
- feel free to yell at me.
I’m curious if anyone has experience the following using bidi (or any other client side routing): navigating around with links in the app works fine, and keeps track of things like user log in state, but if I directly type in and navigate to an address, the entire app reloads, losing all state. Most likely I’m neglecting to do something very basic with session or something, anyone recognise a common newbie pitfall?
I think that has nothing to do with bidi for that matter. You can listen to hash change event, but I'm not sure if there's something similar for URL change.
jaen: I think the problem is my app-db (using re-frame) doesn’t persist across reload. When i navigate routes with links, they’re nearly instantaneous, but when I reload or manually go to a page, it seems like the whole app is loading again. if my init
fn looks like this:
(defn ^:export init []
(routes/start!)
(rf/dispatch-sync [:initialize-db])
(reagent/render
[views/app]
(.getElementById js/document "app")))
what else could be wrong?Because well, as you say - you reload. Your page will get loaded again, can't do much about that.
Then you could serialise it using, say, transit and store in local storage using, for example, hodgepodge or something.
Wow so by default all apps with this architecture won’t persist app-db? That makes sense, but it’s a little surprising.
Sorry to keep asking so many questions, but could you steer me towards how to do what you said with the local storage?
^^this would mean that any re-frame apps would log out their users when they reload page, right?
It's really not all that complicated, hodgepodge exposes it as ITransientAssociative
so you can just do (assoc! hodgepodge.core/local-storeage :your-key "your-value)
And yes, when you reload a page in the browser all in-memory state goes away, no matter what language you use.
no after staring at code all day my reading comprehension is a little off :) might need parens around grammatical clauses
So you have to store what you don't want to loose somewhere, like local storage for example.
so... Form1,2,3... I have a component-did-update
hook that is rerun every time the component arguments (i.e. loc
in [google-map loc]
) change, however when using loc
in the code it refers to the initial value — any pointers how to make that change as well?
I tried using :component-did-update (fn [this loc] ...)
similar as it is recommended for the render fn but that didn't do the trick
Hm, according to React's docs componentDidUpdate
gets previous props and componentWillUpdate
will get next props.
huh, so apparently did-update gets [this [some-fn props]]
Where some-fn
seems to be the result of the create-class
call
:component-will-update
;; not sure if I've fully understood why the signature is this way.
;; the first item in the second arg seems to be the return value of
;; the create-class call (seems!)
(fn [this [_ new-center]]
(.panTo (:map <@U06QXASV8>) new-center))
hello, I need someone adventurous. I need feedback on my (kinda) framework for reagent apps, I can offer an incomplete readme and an example app. I'm planning to release it soon (it works for me "tm") but I'd like some feedback before everyone calls me an idiot
@mihaelkonjevic: just provide a link, I'm sure some people here will be happy to take a look
well here it goes: - lib/framework: https://bitbucket.org/retro/keechma - example app: https://bitbucket.org/retro/place-my-order . Place my order app is ported/rewrittent from the https://github.com/donejs/place-my-order app which is used as an example for the http://donejs.com/ framework
readme for the place-my-order-app is inside the client
folder