Lifecycle callback initialize called twice when DOM element is replaced

The docs states that the initialize method is called once in init(i supposed once when the page was loaded), whereas the connect is also called when the markup re-appears. To quote the docs on reconnection:

When this happens, such as after removing the controller’s element from the document and then re-attaching it, Stimulus will reuse the element’s previous controller instance, calling its connect() method multiple times.

Am i missing something or do the re-connect docs need to be updated, with something like: ONLY works with turbolinks. As this does not work in a simple case where an xhr call replaces a DOM Element with a controller markup(not just the child elements). The only posts i found where related to turbolinked setups, which i dont use at all.

After reading the lifecycle_tests.ts it seems like te reconnect only reacts to removeChild calls, whereas i am replacing a whole part of the DOM, not just a single controller enabled element. I’ll continue to read to sources to found out more about the matching of re-appearing elements … pretty puzzling.

I know there are possibilities like a global/wrapper controller to persists controller specific settings, but the idea of initialize is actually there to prevent such.

I am using stimulus atm as an autoloader system, replacing all those jquery-ready calls across my different js modules. I import all controllers in my pack index file, start the application and register everything manually, instead of using the webpack-magic module loader.

I get why this can be confusing. When you use XHR to replace an element in the DOM, the new element might look completely identical to the old one, but in the eyes of the DOM, it’s an entirely new node.

This is important because a Stimulus controller instance is associated with a specific DOM node. If that node gets replaced, its disconnect method is called, and the connect method is then called on the new node’s controller instance.

The connect method is only invoked again on the same controller instance if the element node is detached and re-attached to the DOM.

Thanks for the clarification! Makes sense and proved my guessing.

So a general advice would be to only replace the innerHTML to keep the DOM node around or persist data in another controller instance higher up the DOM tree.

1 Like