Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Choo v5 / v6 onload handlers on root node not called when navigating #490

Closed
mantoni opened this issue May 9, 2017 · 16 comments
Closed

Comments

@mantoni
Copy link
Contributor

mantoni commented May 9, 2017

Steps to reproduce behavior

Create two pages:

  • /foo with root <div>
  • /bar with root <div onload=${myHandler}>

Expected behavior

Navigating from /foo to /bar triggers the onload handler

Actual behavior

The onload handler is not triggered upon navigation. It is triggered when loading the /bar page initially though.

Workaround

Attaching the onload handler to a child node fixes the issue.

The workaround is simple enough to apply. If this is tricky to solve, I think an assertion would also do.

@bengourley
Copy link
Contributor

If I understand it correctly, this is a typical nanomorph/morphdom issue… when you navigate between routes, the diffing algorithm compares…

before: <div></div>
after: <div onload=${fn}></div>

It sees that the element that exists is already a <div> so doesn't need to replace it, just add an attribute. Since the semantics of onload are "when the element is added to the DOM" and this element is already in the DOM, it correctly (but confusingly) doesn't fire.

I don't know what the best approach for your problem is this but I hope this helps explain why it doesn't work!

@mantoni
Copy link
Contributor Author

mantoni commented May 9, 2017

@bengourley Thanks for elaborating. I'm aware of this behavior, but still crashed into this and got confused. It should somehow be handled or highlighted by Choo, I think.

@josephluck
Copy link

josephluck commented May 9, 2017 via email

@mantoni
Copy link
Contributor Author

mantoni commented May 10, 2017

No, setting unique IDs on the nodes does not help. Actually, the onload handler generates dynamic data properties that are already unique (as long as the called handler function is different).

Here is a minimal Choo app to illustrate the issue:

var html = require('choo/html')
var choo = require('choo')

var app = choo()

function onloadA() {
  console.log('onload A')
}

function onloadB() {
  console.log('onload B')
}

app.route('/a', function (state, emit) {
  return html`<div onload=${onloadA} id="a"><a href="/b">Go to B</a></div>`
})
app.route('/b', function (state, emit) {
  return html`<div onload=${onloadB} id="b"><a href="/a">Go to A</a></div>`
})

document.body.appendChild(app.start())

Save as issue.js, run with budo issue.js --pushstate and open http://localhost:9966/a.

@mantoni
Copy link
Contributor Author

mantoni commented May 10, 2017

Actually, if you look at the DOM changes when navigating between /a and /b, you can observe that the id property is changed on the root node while the data-onloadHASH property is not. Only onload A makes it to the console on first load.

@nilliams
Copy link

nilliams commented May 15, 2017

I just hit this too and can confirm the issue.

Edit: Speculated about using data-onloadid as a workaround, but deleted as I realised I have no idea of the intended use for that.

@yoshuawuyts
Copy link
Member

yoshuawuyts commented May 17, 2017 via email

@yoshuawuyts
Copy link
Member

choojs/nanomorph#63 will land in choo v6 ✨

@mantoni
Copy link
Contributor Author

mantoni commented Oct 23, 2017

I had another look with Choo 6.0 and Choo 6.5. Now none of the onload handlers is fired anymore with the example posted above. Previously, at least the initial onload handler was fired. Is this intentional and root node onload is not supported at all anymore?

@mantoni mantoni changed the title Choo v5 onload handlers on root node not called when navigating Choo v5 / v6 onload handlers on root node not called when navigating Oct 23, 2017
@yoshuawuyts
Copy link
Member

@mantoni yeah, we removed it entirely — this was a breaking change in v6.0.0, but needed to happen because using onload with DOM diffing doesn't work. We recommend using nanocomponent instead!

Does that make sense?

@mantoni
Copy link
Contributor Author

mantoni commented Oct 23, 2017

Makes sense. It's at least consistent now. However, I'd personally think this is a common thing to try when playing with Choo. How about adding an assertion?

@yoshuawuyts
Copy link
Member

yoshuawuyts commented Oct 23, 2017 via email

@mantoni
Copy link
Contributor Author

mantoni commented Oct 23, 2017

I‘m mean that Choo should throw if you’re using onload on a root element. Because it’s working otherwise, just not on the root.

@yoshuawuyts
Copy link
Member

@mantoni please check you're running the latest bel; I made sure to remove it in a major version a couple of months ago. There's valid use cases for an onload attribute that acts differently from the on-load package, so throwing when it's used would probably be a conflicting (breaking even) change. Does this make sense?

@mantoni
Copy link
Contributor Author

mantoni commented Oct 30, 2017

@yoshuawuyts Thanks for the pointer. Took me a while to find out why my code is still working 😅

Turns out I'm always going through yo-yoify and never hit bel directly. The onload feature was not removed from yo-yoify (yet).

Closing issue since it's by design. However, I'm not sure how I'm supposed to migrate my codebase once onload stops working. I depend heavily on this feature and using the on-load library is not as convenient 🤔

@mantoni mantoni closed this as completed Oct 30, 2017
@yoshuawuyts
Copy link
Member

yoshuawuyts commented Oct 30, 2017 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants