Anj Anj - 3 months ago 17
Javascript Question

What are the differences between using <compose view-model="./my-element"> and <my-element>? What are some scenarios where one is more suitable?

A teammate and I have been building an application in Aurelia for the last four months, and he and I have been creating and using components in these two different ways. I want to have some consistency and change everything over to one of the two styles, but I don't know which one is preferred or more suitable for our needs.

I chose to use

<compose>
because to me it feels cleaner and suits every need I have encountered, but if using the custom element is objectively better I want to switch to that.

For example:

(his-way view-model:)

import { bindable, bindingMode } from 'aurelia-framework';

export class HisWay {
@bindable({ defaultBindingMode: bindingMode.twoWay }) data;
}


(his-way view:)

<require from="./his-way"></require>
<his-way data.two-way="myModel" containerless></project-name>


(my-way view-model:)

export class MyWay {
activate(model) {
this.model = model;
}
}


(my-way view:)

<compose view-model="./my-way" model.bind="myModel" containerless></compose>


Do I need to change over, and if not, what are some reasons I can use to persuade him to using the same style that I have been using?

Answer

Use the custom element approach when possible.

Compose targets dynamic scenarios. If your <compose> element's view and view-model attribute values are static (not data-bound) you probably should have used a custom element for the reasons described below.

Portablity: Custom elements are more portable because they have a higher degree of encapsulation. A custom element's template cannot access the outer scope, all data must be passed in via @bindable properties. This contrasts with <compose>, which allows accessing the outer scope, making it very easy to get sloppy and make assumptions about the environment in which a composed view will be used.

Features: Custom elements have more features than the <compose> element. Template parts/slots (transclusion), bindable properties, ability to "globalize" via globalResources and more.

Reuse: It's much easier for a team to reuse a widget when it's encapsulated in a custom element and globalized via globalResources. The team can simply write <mega-widget ...></mega-widget> as opposed to having to remember the relative path to mega-widget.html and mega-widget.js and write a valid <compose view="..." view-model="..."></compose> expression.

Better fit: Any use-case where you are creating a data-entry widget really deserves a custom element. It's far easier to use a currency custom element- eg: <currency value.bind="unitCost"></currency> than it would be to try and achieve similar results with <compose>. Not sure how you would accomplish it really.

CSS: it's easier to target a custom element with css selectors than a specific compose element instance. mega-element { display: block; ... }