Closed sigmer closed 7 years ago
I guess this was more of a general ember question. I did it by resetting the app with Ember.Application.reset() when new components are dynamically added. Probably not the best thing to do.
That's an interesting solution. It might be a little heavy since it clears out all the objects that Ember has, but in this case that might not be much.
Someone else asked this same question recently (maybe it was you!), so I'm wondering if we should come up with a better solution. The first thing that comes to mind is exposing some global function EmberIslands.rerender()
that would check the list of rendered elements, tearing down any whose DOM element has been removed and adding new components whenever an new marker is found.
What do you think?
Mitch, I asked the same question and thanks for your response. Look forward to your solution for it.
A global function that handles removed/added island elements would be very useful in this situation. I think it's better than resetting the ember application. Thanks!
Your addon is a great bridge to introduce ember in a large, server rendered app.
I'd also love to see something like this! I'm loading remote modal content and I'd like to be able to have an ember component rendered in the modal
Note to self or someone else wanting to tackle this:
This can probably be accomplished while still adhering to the public API of Ember's components.
Add an option to install and remove a global reference to the component on init
and destroy
. It might even make sense to leave this up to users and add documentation. Users can then call the public rerender
method on the component.
In the didUpdate
or willUpdate
hook (not sure which is better)
destroy()
any components that no longer have an elementrerender()
components that are still on the pagerenderComponent
for any new componentsEdit: This approach changed quite a bit. Overloading these hooks had some complications and didn't provide much value given that users just need some global function to call and shouldn't have to know much about the ember-islands component itself.
I'm interested in this as well 😀
Took a shot at this tonight. The implementation in Ember Islands simple, but there is an issue with how Ember handle's destroying root components that currently makes this infeasible.
As of this commit Ember does not remove root elements from the renderer when they are "cleaned up". This means that if you remove DOM, you'll be leaking memory since the list of components referenced by this._roots
will never get smaller. In Ember Islands tests with manifests with a error:
Error: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
Which comes when Glimmer is trying to clear
the root component which is no longer in the DOM.
As always, landing splat in Ember would mean we could stop using multiple root elements which would fix this problem. Also I'm curious if the new Component Manager API could help us get away from rendering multiple root nodes.
In any event the next task here is probably to add a test to this file that shows you can use appendTo
, call destroy
and remove a root component:
You can try out the new "rerendering" branch by adding this to your package.json:
"dependencies": {
...
"ember-islands": "mitchlloyd/ember-islands#rerendering"
}
Then inside of an initializer, app.js, or any file that is imported in your Ember app:
import { reconcile } from 'ember-islands';
window.whateverNameYouWant = reconcile;
Then whenever you want to "update" your page you can call this global method:
window.whateverNameYouWant();
The reconcile
function does 3 things:
data-attrs
have changed.Let me know if it works out!
A few caveats:
data-component="new-name"
) isn't supported (but could be). Updating the data-attrs
property of a placeholder is supported.Application.reset()
until the next version of Ember lands.Hey @mitchlloyd, your rerendering
branch is great! It's quite useful when not all JS lives within the Ember world. Many thanks for that one!
Are you going to open a PR of your rerendering
branch? I would love to see it in master, if possible.
@felixibel Were you able to get this working on a project? If so great to hear! I definitely need to get feedback on this change since I don't have this use case myself.
I opened a PR (#46) with a few todos on it. I'm expecting to have time to tackle this by next week.
@mitchlloyd This is working in my project. Very excited for this change! I can confirm components are rendered/destroyed when the placeholder divs are added/removed from the page.
I'm not currently dynamically modifying the data-attrs on the div, but that is a cool idea and definitely useful.
Thanks for this!!
Published as 1.3.0
I'm just getting started with ember and I've successfully added some ember components to my server-rendered app using ember islands! But now I have a case where a fragment of html is fetched asynchronously from the server and added to the page. In that html I'd like to define an ember island component. Of course it does not render when inserted into the dom where ember has already booted. Any thoughts on a way to render a component when it's inserted into the page after ember has booted?