This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-08-17
Channels
- # admin-announcements (1)
- # aleph (1)
- # architecture (1)
- # bangalore-clj (14)
- # beginners (15)
- # boot (89)
- # braveandtrue (1)
- # cider (1)
- # cljs-dev (33)
- # cljsjs (1)
- # cljsrn (147)
- # clojure (149)
- # clojure-quebec (1)
- # clojure-russia (82)
- # clojure-spec (18)
- # clojure-taiwan (2)
- # clojure-uk (15)
- # clojurescript (97)
- # cursive (11)
- # datomic (22)
- # funcool (2)
- # hoplon (53)
- # immutant (16)
- # jobs-rus (8)
- # lambdaisland (1)
- # off-topic (13)
- # om (7)
- # onyx (58)
- # parinfer (6)
- # planck (19)
- # protorepl (2)
- # re-frame (17)
- # reagent (201)
- # rum (6)
- # specter (9)
- # test-check (68)
- # untangled (47)
- # yada (94)
I’m interested in whether anyone here has experience of drawing text using SVG from a reagent app? The problem I am facing is knowing, in advance, the width and height of the text to position it correctly. Most solutions I have found use a “hidden render” technique that depends on creating a DOM node and measuring it. That doesn’t appear to be open to me here. Any suggestions?
wondering if this might be too specific a question for this group, bit of an edge case
@sandbags: I like using SVG from reagent, and text... but I tend to just center it over a point and adjust the font size. What are your constraints in terms of positioning? it sounds like an interesting problem.
If you just want to get the width/height I think you could do that with :ref
(see discussion about a page up)
@timothypratley: I’m drawing a spider diagram and I wanted to be able to position the axis labels based on the text centre
but when it came to positioning the axis labels… i’m having to fall back to hand estimation
nice 🙂
^^ I found this helpful
I should mention i have only passing knowledge of react and the underpinnings for using it in CLJS
Hmmm what part is the most confusing? 🙂
no no no, just trying to find the best resource to direct you to.
oh my train is coming in, but i’m interesting so i hope you’ll still be around later and i can ask a few more questions
foo is a component (wow that doesnt help much huh? lol) yup, i'll try to make a more detailed answer later today
<-- this is the best first stop
Understanding components have 3 forms for declaration -- if you get that, you should be good with the refs example.
@sandbags: I've updated the gist with a bit more context
@pesterhazy: thanks, thats very useful. Btw is there a significance to the use of ! in the variable name !ref ?
@timothypratley: ah, i’ve not really tackled reframe yet (just skimmed some of the docs) but it seems there is some good stuff here
@sandbags !
usually means you are mutating something. Think swap!
in relation to an atom or something of that nature
although i’m not clear since in principle the places where either can be mutated are fairly delineated and, at other times, their value can be relied upon… or so I think
@sandbags sorry i didnt actually look at the code snippet. I dont know the prefix use of ! In that context. I wouldn't use it on an atom itself.
if it’s being used as a kind of flag to the reader “Hey this is an atom” I guess that could be useful although in practice you see the @ so...
Yeah, i havent seen the prefix bang, but perhaps i just havent noticed. Ive only ever used it at the end to signal that i am doing a mutation
@timothypratley: that was very useful thank you and @pesterhazy’s gist is now relatively clearer. I presume I am interested in the componentDidMount react lifecycle method
looking at the source of create-class
the callback is :component-did-mount (fn [this])
where i assume this
is the DOM node of the mounted component?
yeah the leading !
is a somewhat idiosyncratic convention some people use to indicate reference types (mainly atoms)
yes, this
is the component
@pesterhazy: when you say “the component” do you mean the DOM node representing the component? Or the reagent data structure that you pass to create-class
?
@sandbags: you may find (reagent/dom-node this)
useful. (Keep your eyes on this issue tho ... react may do away with findDOMNode https://github.com/reagent-project/reagent/issues/251)
as @gadfly361 says, it's not the DOM node but the internal React representation of the component, I think
I am trying to grok the example @gadfly361 just posted (thank you @gadfly361)
@sandbags: here is an example that uses dom-node
: https://github.com/reagent-project/reagent-cookbook/tree/master/recipes/highcharts
so if you pass :ref #() as an attribute of some markup your component generates, that function will be called at some point in the render process passing in the DOM node reference that you can stash away for later use, am I understanding that right?
that's my assumption, yes
if you're in doubt, try prn
'ing the data structure that is passed to the ref attributes and see what you get
you don't need a form-3 component, no
though at some point you'll want to do something with the ref, and a lifecycle method is probably the best place for that
hrmm… perhaps i did something wrong, i added a :ref (fn [x] ..) but it doesn’t seem to have been called
thank you @timothypratley, @pesterhazy, and @gadfly361 I’m not there yet but at least I know how I will get there
what does it give you?
that looks like a dom node 🙂
i wonder how fast this will all work, my hope is that it will be essentially instantaneous and you won’t see the text “snap” into place
my next task is PDF generation… I suspect it won’t be as much fun… it’s not even a day job!
@pesterhazy: looking again at your gist is your !ref
a clojure atom or a reagent atom?
i’m guessing from what i read in the reframe docs you want to use a clojure atom as you don’t want it entangled with the tracking thing
clojure atom, as you don't need to keep track of updates to it
good luck with this!
reagent is severely lacking in documentation, we should start putting up stuff like this on the wiki
there's especially too little information out there on how to use the lifecycle methods in reagent
yes, it actually looks pretty straightforward but I would have struggled to infer any of this without your help
yeah, reading the reagent source is not a walk in the park
it's pretty awesome otherwise though 🙂
I think re-frame docs cover pretty well +1 to link @timothypratley shared earlier
re-frame docs cover a lot of missing surface area, but not all (e.g. lifecycle methods -- what parameters do they receive exactly?)
hrmm… trying to wrap my head around this. I write my component render function and put a :ref fn in to get access to the DOM node, after it’s mounted I get the width & height of the bounding box but then I want to go back and amend the :x
and :y
values passed into the component but… mental model breaks
We should make it more prominent, but this is in the reagent wiki: https://github.com/reagent-project/reagent/wiki/Creating-Components
did-mount will happen before render
the args to the render fn... you are doing that part right.
x y label.
they don't actually pass through as such
they are 'available' at creation, and 'available' at render.
note that did mount fn takes a 'this' arg
and you can call reagent/dom-node on it
for the bounding box part
well... it depends what you want the bounding box of
I was just confused
if you want the bounding box of the text
then you should call bounding box in the ref fn
what i can’t get my head around though, is how i - having obtained the bounding box - go back and tell the component it has a different :x
and :y
there’s also something about this form-3 function that isn’t right in my head… how do the values for :x
, :y
, and :label
arrive at the reagent-render
function if they go nowhere in my axis-label-component
function...
I'm thinking something like: (let [text-width (reagent/atom 0)] (fn [] [:text {:x @text-width :ref (fn [cmp] (reset! text-width ....)))} "oh my gawd"]))
@timothypratley: i wasn’t sure if the node was fully rendered until after didmount
but I haven't tested it.
(if that works, consider setting a style "hidden" when the text-width is 0 (or nil)
Can you explain because I am pretty confused about this: I pass in values x
, y
, label
to my component function axis-label-component
but these values go nowhere because they are shadowed in the reagent-render
function. How do these values end up getting passed to the reagent-render
function at all?
🙂 It's weird huh?
Let's talk about form 2 first:
(defn a [x] (fn b [x] [:div "foo"]))
a returns a function, that has hiccup in it
say I have this code:
and 'a' doesn't exist in the DOM
a is going to get called
with 1 as the argument
but only once, when it gets added to the DOM
b is going to get called lots of times
to render (if something changed that it depends on.
I don't call a at all
a is in a vector
@sandbags: this may or may not be useful to read: https://github.com/reagent-project/reagent-cookbook/tree/master/basics/basic-component
I just replaced my use of [:text] directly within the containing component with a call to my axis-label-component
component function
it's not 'wrong' but it's not the reactive way 😛 you should use a vector instead. [axis-label-component ....]
functions get called immediately
being in a vector is the way reagent can do things only if something changes.
I didn’t fully appreciate the vector thing as it (mostly) seemed to work using functions and I thought once I used a vector with arguments and nothing happened
so reagent calls the component function with the arguments and, then, calls the render function with the same arguments (at some point)
:thumbsup:
so this
in the component-did-mount
function looks like something else than what i see in the ref
function
yeah, the this
that context is the reagent component, not the element. calling reagent/dom-node on it will give you the element though if you want it.
but I don't think you need to use the mount path at all for what you are doing.
now i have to change the x
and y
values of the text component to the adjusted values (and set visibility
back from hidden)… but the only way I know of to get a component to update is to have it depend on a ratom
so i guess i actually do want my component to create a reagent atom rather than a clojure atom
and thanks @timothypratley for suggesting the visibility trick, mightn’t have thought of that
nice! seeing you only specify the render fn, you don't need the create-class form at all (a function that returns a function will work here)
thanks again to all three of you… i feel i have moved from unconscious incompetence to conscious incompetence in one evening
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor <-- setting this to 'middle' will center it on the x coord, which in hindsight seems to be what (- x (/ (:width @dom-data) 2))
does.