I am working on an existing SPA where we replace components with Aurelia components step by step. We use the enhance
API of the TemplatingEngine
. That works pretty well but we also need to tear down those enhanced fragments (remove event listeners, ...) when moving to another part of the application (no page reload).
My idea is to keep the aurelia instance in the page and reuse it.
Currently I enhance fragments like this:
function enhanceFragment(targetElement) {
function proceed() {
let aurelia = window.DFAurelia;
let engine = aurelia.container.get(TemplatingEngine);
engine.enhance({
container: aurelia.container,
element: targetElement,
resources: aurelia.resources
});
}
if (!window.DFAurelia) {
bootstrap(async aurelia => {
aurelia.use
.defaultBindingLanguage()
.defaultResources()
.eventAggregator()
.developmentLogging()
.globalResources('app/df-element');
await aurelia.start();
window.DFAurelia = aurelia;
proceed();
});
} else {
proceed();
}
}
The HTML I enhance looks like:
<df-element></df-element>
I tried this in a function of the custom element itself (DfElement::removeMyself()
):
let vs: ViewSlot = this.container.get(ViewSlot);
let view: View = this.container.get(View);
vs.remove(view);
vs.detached();
vs.unbind();
but I get an error when getting the view from the container (Cannot read property 'resources' of undefined). I called this function from a click handler.
Main question: how to manually trigger the unbind
and detached
hooks of the DfElement
and its children?
Bonus questions: properties of my aurelia
instance (window.DFAurelia
) root
and host
are undefined: is that a bad thing? Do you see any potential issue with this way of enhancing (and un-enhancing) fragments in the page?
Use the
View
returned from theenhance()
method.The
enhance()
method returns the enhancedView
object. It is a good practice to manage the teardown from the same location where you callenhance()
, as you may not be able to trust an element to remember to tear itself down. However, you can always register theView
instance with the enhance container to access it from within the custom element.This will tell the DI container to respond to calls for
View
with thisView
.Using the
created(view)
lifecycle methodA much better practice would be to use the
created(view)
lifecycle method in your custom element.This is a much more straightforward, best practices way of having a custom element grab its own
View
. However, when trying to write this answer for you, I tested nesting a custom element in a<compose>
element. The result was that theView
in my custom element was actually theView
for my<compose>
element, andremoveMyself()
removed the<compose>
entirely.