Closed jmstacey closed 7 years ago
No joy after digging through the stack. I don't fully understand the virtualdom internals so it's possible I'm missing something. While I could get a vdom hook to fire, it would be called right after the render to the virtual dom. What I need is a hook right after the virtual dom has been patched.
I brought back this bit of code in PR https://github.com/inesita-rb/inesita/pull/32 and it seems to be working in the sample below:
def before_render
Element['#outline'].nestable('destroy')
# Deactivate nestable plugin so it can be rebuilt from the state store
end
def after_render
Element['#outline'].nestable({ 'json': store.app.state.visible_data, 'callback': -> { on_dd_change(l, e) } }.to_n)
# Todo (caution): binding persists across route changes and may break other component trees
end
def render
# Works w/ restored after_render hooks in https://github.com/inesita-rb/inesita/pull/32
div class: "dd", id: "outline"
# Does not work. #after_render is called after this render block but before vdom changes are applied to the real DOM
div class: "dd", id: "outline", hook: hook(:after_render)
end
If there's a better way to pull in JQuery plugins that directly change the real DOM I'm all ears.
Hi, You're close. Hook callbacks give you a node reference. Instead of querying node with the Element
, you should use this reference.
Here is an example: https://github.com/fazibear/web-audio-playground/blob/master/app/layout.rb#L11
Also, hook usage should be included in the documentation.
I'm still stumped. The web-audio-playground example isn't doing anything with the node reference in the vdom callback so all changes are happening natively from the Inesita render.
In the case of this jQuery nestable2 plugin it's expecting a DOM node, not vdom. Are you saying there's some way to hook this up so it'll work like that?
Other frameworks such as React and Vue introduce lifecycle events like onComponentDidMount and componentWillUnmount where they inject the JQuery plugin initialize.
Any suggestions?
Here's the full source I have for reference: https://github.com/jmstacey/dnd_list/blob/master/app/components/outline.rb#L23-L33 If you hack at that remember to use an alternate to #after_render, like #after_render_tmp, since the former will be called by the modifications in the PR.
In web-audio-playground
example hook is used to draw the line between two dom elements. To get offset
or width
properties vdom elements must be attached to dom.
You can try:
def after_render(node)
# Element[node] or just node
Element[node].nestable({ 'json': store.app.state.visible_data, 'callback': -> { on_dd_change(l, e) } }.to_n)
end
div class: "dd", id: "outline", hook: hook(:after_render)
Or try to hook outer element and select inner nodes with jqeury`
I'm wondering why you try to mix vdom with jquery. It's really hard to deal with it.
I'm wondering why you try to mix vdom with jquery. It's really hard to deal with it.
Indeed, and it feels wrong. Upside is that a lot of existing code that works today can be reused without rewriting into native components. More complex examples could be charting libraries, maps, and so forth.
It's a challenge with the other frameworks as well. Here are a few examples how some of them handled this--common theme is the idea of mount and unmount hooks to create sections of DOM that aren't managed by the virtual dom. clearwater blackbox nodes Wrapping jQuery with React Vue.js virtualDOM mixing with jQuery plugin
I didn't have any luck with Element[node].
, or node.nestable(. . .
since it's triggered in the wrong context [nestable manages the dom]. In comparison to the playground example, that's a native component implementation and the DOM is entirely managed by Inesita and the vdom.
Perhaps modify the after_render PR to follow a similar convention with #on_mount and #will_unmount?
Hook gives you a reference to given node, just after mount.
Here is the example:
def after_render(node)
Element[node.to_n].nestable({ 'json': store.app.state.visible_data, 'callback': -> { on_dd_change(l, e) } }.to_n) # #to_n converts to native javascript. Provided by opal-jquery
# Todo (caution): nestable binding is on real DOM and is likely to break on route changes. Consider a "terminate" equivalent to unload on other pages.
end
def render
div class: "dd", id: "outline", hook: hook(:after_render)
..
end
I see the after_render hook was removed about a year ago and replaced with hook and unhook in VirtualDOM, but I can't reason out how to use this for my use case. Examples or alternative solutions would be helpful.
In my case I'm using the nestable2 JQuery plugin that of course directly manipulates the DOM. I need the virtual DOM diff to be applied before I mount the JQuery plugin to the element. Right now I have it all working except for overcoming the first DOM load--so I have to click on the same nav link 3 times which for reasons I haven't figured out allow nestable to then hook on to its target element and start working.
This surprisingly works combined with the store including versioning, but I haven't been able to overcome the first page load issue.
Grateful for any tips and examples.