aureliaaurelia-templating

Aurelia - dynamically create custom element in a view-model


I have an Aurelia app where a user can click on a button and create a new tab. The tab and its content (a custom element) do not exist on the page before the user clicks the button. I am generating the HTML for the content at runtime (via Javascript) in my view model.

I keep seeing mention of using the template engine's compose or enhance functions, but neither are working for me. I don't know how I would use the <compose> element (in my HTML) since I am creating the element based on the user clicking a button.

My thought was that the button has a click.delegate to a function that does ultimately does something like

const customElement = document.createElement('custom-element');
parentElement.appendChild(customElement);

const view = this.templatingEngine.enhance({
  element        : customElement,
  container      : this.container, // injected
  resources      : this.viewResources, // injected
  bindingContext: {
    attrOne: this.foo,
    attrTwo: this.bar,
  }
});

view.attached();

But all this does is create an HTML element <custom-element></custom-element> without actually binding any attributes to it.

How can I create a custom element analogous to <custom-element attr-one.bind="foo" attr-two.bind="bar"></custom-element> but via Javascript?


Solution

  • As you pointed out in your own answer, it's the missing resources that caused the issue. One solution is to register it globally. That is not always the desired behavior though, as sometimes you want to lazily load the resources and enhance some lazy piece of HTML. Enhance API accepts an option for the resources that you want to compile the view with. So you can do this:

    .enhance({
      resources: new ViewResources(myGlobalResources) // alter the view resources here
    })
    

    for the view resources, if you want to get it from a particular custom element, you can hook into the created lifecycle and get it, or you can inject the container and retrieve it via container.get(ViewResources)