Fork me on GitHub
#reagent
<
2015-08-30
>
benzen05:08:52

Toi can use an event listener for this

benzen05:08:50

The event you will recieve has a target proporty

jonaskello07:08:53

@benzen Thanks simple_smile I’m converting some code that is currently working differently but I think that will solve my scenario. Still would be interesting to know how to interact with dom nodes in Reagent. The only info I could find is this but it seems old since it references cloact: https://github.com/reagent-project/reagent/issues/5

jonas07:08:13

@jonaskello: I’m also interested in learning about ‘ref’ support in reagent. You can sometimes use id’s instead but that’s not very idiomatic React IIUC. Let me know if you learn anything interesting in this area

jonaskello09:08:45

@jonas I managed to solve my current scenario with a combination of event.target to get the td and getElementById to get the div. I agree the getElementById does not seem like the correct way to do it in react, not even sure it will work in all situations? I’ll keep looking for a more correct way to reference the div and post if I find it..

jonas09:08:37

@jonaskello: This seems to work: (.findDOMNode js/React (-> this .-refs .-myRef)) where my component has a ref set on one of the DOM nodes, for example [:p {:ref “myRef”}]

jonaskello09:08:53

@jonas That seems like a good way… I’m new to clojurescript so I’m a bit unsure how the (-> this .-refs .-myRef) part works… if I try it, figwheel tells me “this” is an undeclared Var… I guess “this” is a clojurescript reference rather than a js reference in this context?

jonaskello09:08:34

Do I need to use with-meta and component did mount to get a reference to this?

jonas10:08:08

@jonaskello: Yes, it would go in :component-did-mount

mikethompson12:08:03

@jonas: i always wince when I see the the with-meta form of adding lifecycle methods. Are you aware of this method: https://github.com/Day8/re-frame/wiki/Creating-Reagent-Components#form-3-a-class-with-life-cycle-methods

mikethompson12:08:40

No, wait! Ignore. I've read further now. simple_smile

jonaskello13:08:15

@jonas Thanks for the snippets! I’ll see if I can make it work in my scenario

jonaskello13:08:50

@mikethompson: Would Form-3 not work in this case? Never mind, saw the second example had it now simple_smile

paulspencerwilliams13:08:40

Hi all, nearly managed to wire up a sample Reagent app presenting data from an atom in a Highcharts chart. Updating the atom works find, but the Highchart binding doesn’t fire when the atom is updated. If I force a refresh via figwheel by updating code, the graph does get updated. Any pointers - I think I’m closer to understanding the basics.. https://gist.github.com/paulspencerwilliams/0b9a9d00869ec9107d4a

darwin14:08:46

@paulspencerwilliams: try to deref chart-config in graph-container

darwin14:08:19

you can throw it away like (let [_ @chart-config] ...)

darwin14:08:00

right now, no rendering function depends on chart-config data, so reagent won’t re-render them when you touch chart-config atom

paulspencerwilliams14:08:51

@darwin: yeah, that’s what I thought, but couldn’t see how to trigger it. The token deref didn’t work, but I think it’s the right general direction.

darwin14:08:19

but there is probably a better solution, you want tell highcharts to update itself, without discarding whole dom element and building up from scratch again

jonaskello14:08:24

@jonas The examples are really close, only I need to use .findDOMNode in an onclick handler, which means I need a reference to “this” in the onclick handler… Not sure how to get that….

paulspencerwilliams14:08:46

@darwin: I was reading https://github.com/Day8/re-frame/wiki/Creating-Reagent-Components which is nearly there, but it isn’t quite sinking in.

darwin14:08:15

ah, this-as

jonaskello14:08:12

@darwin Aha, and that is a built-in macro in clojurescript?

jonaskello14:08:33

Thanks, did not know that simple_smile

paulspencerwilliams14:08:26

@darwin: suppose, in a way, I want a component that on change doesn’t ‘return html’ but rather invokes a JS function.

paulspencerwilliams14:08:52

@darwin: but maybe that’s me thinking imperatively.

darwin14:08:18

@paulspencerwilliams: I would recommend building your component as two reagent components, an outer wrapper responsible for creating highcharts element via :component-did-mount as you do now, but not passing in data, and an inner component responsible for feeding it with data, using some highchart api call on existing element, the inner component should deref your data source, do the clj->js work and call the api as a side effect of its rendering

darwin14:08:36

reagent/react are smart enough to keep your outer component living between render calls to the render function of the inner component (because no inputs changed for that outer component)

darwin14:08:23

in figwheel case, whole dom tree will get rendered from scratch, because r/render-component is called when figwheel re-evaluates the source

paulspencerwilliams14:08:50

@darwin: can use chart.series[0].update etc (http://stackoverflow.com/questions/16407901/highchart-series-update-in-javascript) to update Highcharts, but again, this is getting a component to run JS rather than returning HTML, and it seems only atoms referenced in returning HTML will cause the component to be re-referenced.

darwin15:08:02

@paulspencerwilliams: in your inner render function you should do both, return hiccup and (as a side effect) run some js code (call chart’s update method)

darwin15:08:33

causing side effects in your render functions is not nice, but that’s the way how to deal with mutable js-world

paulspencerwilliams15:08:36

@darwin: suppose the constraint I’ve been focused on is the JS references the html returned in hiccup, but the JS will execute before the hiccup is executed, and thus the html element won’t exist at the time.

paulspencerwilliams15:08:08

@darwin: think you’ve hit the nail on the head there - I’m using Highcharts mutably.

darwin15:08:29

by the time inner render function is called, the outer component already exists in the dom (component-did-mount already executed), that is how react works

paulspencerwilliams15:08:51

right, i’ll try this then.

darwin15:08:16

btw. that inner render function should be a fn returning hiccup, not a static array of hiccup markup

paulspencerwilliams15:08:39

yeah, understood; and cheers!

darwin15:08:54

I’m pretty sure this approach will work, you can show me your updated code and I can point out mistakes, if any

paulspencerwilliams15:08:48

@darwin: not using your exact solution, but the approach of causing token side effect.

darwin15:08:44

@paulspencerwilliams: that works, but you are possibly re-creating highcharts element every time from scratch (don’t know if the library is smart enough to apply only changes if the element already exists)

paulspencerwilliams15:08:10

@darwin: apparently so. First step was getting it ‘working’. Second step is to use this approach : chart.series[0].update({ pointStart: newSeries[0].pointStart, data: newSeries[0].data }, true);

paulspencerwilliams15:08:36

Difficulty is this approach requires having a reference to the chart.

paulspencerwilliams15:08:50

suppose mixing mutable JS components isn’t the best introduction to react / reagent 😉

darwin15:08:02

right now, use jquery with your hard-coded element id

darwin15:08:20

I will show you how to make it more flexible, have to look some code up

darwin15:08:58

:component-did-update and other functions are passed calling react component as a parameter, you can ask it to give you root dom node

paulspencerwilliams15:08:16

okay, thanks. For info, this is a learning exercise rather than commercial ‘get it done’ exercise, so I really am looking for idiomatic / clean ways to implement simple_smile

darwin15:08:57

ah, here it is, react component has .getDOMNode function

darwin15:08:04

ideal situation is to end up with a reagent component which is wrapping that js-thing, so that users of the component can treat it as normal reagent component and don’t have to keep special assumptions (about side-effects) in their mind

paulspencerwilliams16:08:54

Dumb question maybe but what exactly does js/$ do?

jonas16:08:30

@paulspencerwilliams: js is a “magic” namespace in clojurescript referencing the toplevel js object (window in browsers and I believe process in Node). So js/$ in cljs is the same object you would get if you were to write $ in a js console. Presumably it’s the jQuery object.

paulspencerwilliams18:08:17

pause for thought?

gadfly36118:08:53

I should read above, looks like there is a discussion around this. And yeah, seems like it should be tucked in a different place

paulspencerwilliams19:08:05

agreed, so holding reference to Highcharts instance is the thing to do. On updating due to atom changing should js invoke series update of Instance?

gadfly36119:08:49

nice, reading that too

paulspencerwilliams19:08:21

I can see Higcharts.charts[0] working for single chart apps and exploring the problem, but not idiomatic. If this was replaced with an in-component reference to the instance, then maybe this is the way forward.

paulspencerwilliams19:08:59

it’s a great blog post though.

gadfly36119:08:05

yeah, that makes sense

paulspencerwilliams20:08:47

@gadfly361 Cheers for snippet, interested in swapping .highcharts and js/$ calls around and need to explore dom-node too. Away from computer now but will look asap. Thanks for effort and to @darwin too. Learning React through an abstraction isn't the easiest, but I'm really enjoying it.

gadfly36120:08:48

@darwin excited to take a look at plastic! simple_smile

darwin20:08:35

@gadfly361: don’t expect much (yet) simple_smile

gadfly36120:08:56

haha looks really impressive so far!