So I found how to build and create an Aurelia Custom Element dynamically via a View/View Slot with the code shown below, however, I don't know how to get its instance (well I found a way but it's ugly)
Here's the util service I have to dynamically create a custom element
export class AureliaUtilService {
constructor(
private container: Container,
private viewCompiler: ViewCompiler,
private viewResources: ViewResources,
) { }
createAureliaViewModelAddToSlot(templateUrl: string, bindableData: any, targetElement?: HTMLElement | Element, clearTargetContent = false): AureliaViewOutput | null {
const viewFactory = this.viewCompiler.compile('<template><compose view-model.bind="template"></compose></template>', this.viewResources);
if (targetElement) {
if (clearTargetContent && targetElement.innerHTML) {
targetElement.innerHTML = '';
}
// Creates a view
const view = viewFactory.create(this.container);
const bindings: any = { template: (templateUrl || ''), ...bindableData };
view.bind(bindings, createOverrideContext(bindings));
// Add the view to the slot
const viewSlot = new ViewSlot(targetElement, true);
if (viewSlot && viewSlot.add) {
viewSlot.add(view);
}
return { view, viewSlot };
}
return null;
}
}
then I call it this way and my custom element is rendered on the screen, yay
const targetElm = document.querySelector('.container');
const templateUrl = PLATFORM.moduleName('custom-element');
const bindings = { collection: this.collection };
const dynamicElement = this.aureliaUtilService.createAureliaViewModelAddToSlot(templateUrl, bindings, targetElm, true);
but now I want and need to modify some properties of that Custom Element, how can I get it's instance? By logging the object in the console, I kinda found the instance by going deep down (really deep that is), but it's ugly, so there must be a better way!?
Here's the deep dive ugly way I found the instance
// first I somehow need to wait the dynamically created Custom Element to fully rendered
// for that I found that I can wrap it in a setTimeout for a full lifecycle to pass
const instance = dynamicElement.view.children[0].children[0].container.viewModel;
// now I can change any of its properties
instance.selectedId = 123;
// I also need to watch for a property changes
// I found that I can do it this way
instance.selectedItemChanged = (item => console.log('item changed', item));
So yeah it works, but there has to be a better way...right?