Aurelia 2 TemplateEngine

In aurelia 1 we did this to use a runtime defined dom element as an aurelia template so that customElements are rendered properly and bindings are set up as expected for an aurelia template:

let view = templatingEngine.enhance({element: modalElement, bindingContext: bindingContext});

TemplatingEngine doesn’t seem to be available in Aurelia 2. What can we do instead?

More context:

// Create modal
let modalElement = document.createElement('dt-modal');
modalElement.setAttribute('view-model.ref', 'dtModalViewModel');
modalElement.innerHTML = `<h3>${title}</h3>${innerHTML}`;

// Add footer to modal
let footerElement = document.createElement('div');
footerElement.setAttribute('slot', 'footer');

// Add ok button
let okButton = document.createElement('button');
okButton.setAttribute('dt-button', 'style:primary');
okButton.setAttribute('click.delegate', 'ok()');
okButton.innerText = 'OK';
footerElement.appendChild(okButton);
modalElement.appendChild(footerElement);

// Add ok button
let cancelButton = document.createElement('button');
cancelButton.setAttribute('dt-button', '');
cancelButton.setAttribute('click.delegate', 'cancel()');
cancelButton.innerText = 'Cancel';
footerElement.appendChild(cancelButton);
modalElement.appendChild(footerElement);

// Add modal to DOM
document.body.appendChild(modalElement)

// Return a promise that resolves when the inner function's return value resolves.
return new Promise(resolve => {
  // Create view model
  let bindingContext = {
    dtModalViewModel: null,
    ok: null,
    cancel: null
  };

  // Enhance aurelia template of modal element
  let view = templatingEngine.enhance({element: modalElement, bindingContext: bindingContext});

  let okButtonClicked = false;

  // Add okButton event handler that is dependent on view
  bindingContext.ok = () => {
    okButtonClicked = true;

    // Clean up modal
    bindingContext.dtModalViewModel.close();

    // Call inner function
    innerFunction(event)
      .finally(() => resolve());
  }

  // Add cancelButton event handler that is dependent on view
  bindingContext.cancel = () => bindingContext.dtModalViewModel.close()

  // Resolve promise when modal is closed. Except if ok button was clicked, in which case promise should not resolved until inner function is completed.
  modalElement.addEventListener('modal-close-start', evt => {
    if (!okButtonClicked) {
      resolve();
    }
  });
  modalElement.addEventListener('modal-close-end', evt => {
    // Clean up modal
    view.unbinding();
    view.dispose();
  });

  // Open modal
  bindingContext.dtModalViewModel.open();
});

With Aurelia2 you need to use Aurelia#enhance. Here is the docs.

Thanks. I will try it out.

Got it working using Aurelia#enhance.
Details:

  • Had to inject aurelia and use non-static method to get access to custom elements registered in the main aurelia instance.
  • Also had to add an outer div element to the dom elements described in first post. Not sure what the problem was, but custom element as root didn’t work, and neither did <template>.

Can you please share a repro?

I’ll need to talk to a guy I’m working with. Might post something Monday.

1 Like

If you run that you’ll see 4 buttons on the home page that reproduce the two scenarios I mentioned.

@tsoiland Thanks for the repro! I need some time to look into it. But will get back to you.

@tsoiland I have gone through your repo. Thanks again for reporting this. Enhancing a custom element should work without a wrapper div. I will look into this.

On a sidenote when you are using the static API, you need to register the custom element before you enhance. It might look something like this:

  Aurelia
+  .register(DtModal)
   .enhance({host: outerElement, component: component})