tobymao / snabberb

A simple component view framework for Ruby Opal based on Snabbdom
MIT License
44 stars 2 forks source link

[BUG] Event handlers not working properly #8

Closed sebyx07 closed 3 years ago

sebyx07 commented 3 years ago

The problem I have is with handling click events and passing a value to it. in snabbdom things are pretty straightforward

function clickHandler(number) {
  console.log("button " + number + " was clicked!");
}
h("div", [
  h("a", { on: { click: [clickHandler, 1] } }),
]);

and this the code I write in opal

click_handler = -> (_, el) do
  p "button" + Native(el).data.on.click[1] + " was clicked!")
end

h(:div, [
  h(:a, {on: click: [click_handler, 1]} )
])

As you can see, you have to go through the element to get to the value, which makes the code not really nice

tobymao commented 3 years ago

can you link me to the docs in snabbdom for this? never knew you could do this

tobymao commented 3 years ago

@sebyx07 so i looked into this,

are you sure snabbdom actually works with this case? i looked into the code and i have no idea how this is possible???

you can see here https://github.com/snabbdom/snabbdom/blob/master/src/modules/eventlisteners.ts#L25

function invokeHandler<N extends keyof HTMLElementEventMap>( handler: SomeListener<N> | Array<SomeListener<N>>, vnode: VNode, event?: Event ): void { if (typeof handler === "function") { // call function handler handler.call(vnode, event, vnode); } else if (typeof handler === "object") { // call multiple handlers for (let i = 0; i < handler.length; i++) { invokeHandler(handler[i], vnode, event); } } }

snabbdom loops through all the elements in the array and does handler.call(vnode, event, vnode) it never calls the handler with the second element passed in the list. can you confirm that this actually works with native javascript code?

tobymao commented 3 years ago

they don't have a unit test for this, so i'm pretty sure the documentation is wrong unless i'm missing something

https://github.com/snabbdom/snabbdom/blob/master/test/unit/eventlisteners.ts

tobymao commented 3 years ago

i filed a bug in snabbdom, please let me know if this actually does work in pure javascript https://github.com/snabbdom/snabbdom/issues/988

sebyx07 commented 3 years ago

I managed to fix it in a way, by wrapping the passed proc in another proc that calls the rest of list

sebyx07 commented 3 years ago

Here is the code, I'm building a POC of writing rails w/o js and HTML. And make it reactive, similar to meteor https://github.com/sebyx07/rails-no-js/blob/master/app/assets/javascripts/components/simple_list.js.rb

I managed to use your library from

h(:div, {class: { "class-name-1": true, }}[h(:a, "ok")])

to

div(class: "class-name") do
  a { "ok" }
end

using metaprogramming

and also to mount components in html.erb / abre, like

<div>
  <%= MyComponent(props: { x: 1}) %>
</div>

w/o actually having the components available inside the ruby on the server

tobymao commented 3 years ago

i'm going to close this issue now because i think the bug is upstream, so snabbdom performs exactly the same as snabbdom

tobymao commented 3 years ago

confirmed that this is outdated documentation on snabbdoms end