6

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?

Randy
  • 9,419
  • 5
  • 39
  • 56
Anj
  • 974
  • 2
  • 10
  • 22
  • One difference is the custom-element tag, wich I find very useful for my CSS. That is reason for me to use `` instead of ``. – Randy Aug 11 '16 at 08:17
  • Our designer doesn't like the dealing with the custom elements themselves, which is why we use `containerless` everywhere. I can't say I agree with the sentiment. – Anj Aug 11 '16 at 11:58
  • 1
    When using `` you can render a component that will be defined at run time. For instance, ``. Another advantage is that with `` you can reuse views and view-models. You can use the same view for 2 different components – Fabio Aug 11 '16 at 13:57
  • 1
    @FabioLuz These are good points, and I forgot about them although I have used `` in this way already. Thanks! – Anj Aug 11 '16 at 17:02
  • You can although make the choice of the view dynamic for a component as well by using useViewStrategy() – zewa666 Aug 12 '16 at 13:49

4 Answers4

9

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; ... }

https://www.danyow.net/aurelia-custom-element-vs-compose/

Jeremy Danyow
  • 26,470
  • 12
  • 87
  • 133
  • This is exactly the kind of response I was hoping for. Thank you. – Anj Aug 13 '16 at 13:59
  • This is a great explanation. I will recommend that you request this to be added to the official docs. As a new Aurelia learner, this was much more helpful than what's currently there. – reggaemahn Jul 08 '18 at 23:32
1

I personally wouldn't force yourself into only using a certain approach. Most frameworks suffer from the fact that they try to convince you that there is only one winning paradigm. But thats not true since each project, and even inside the project each requirement can be completely different.

So when looking at whether to render components using the custom element name vs compose, first ask yourself what is the design goal you want to achieve. Unification in my opinion is not enough.

Going only with the custom-element approach is great because its easy to read and easy to get going for a kinda static page structure. On the other hand if your page requires a lot of dynamic composition, the composed approach as the name suggests is the way to go.

So I'd tend to agree that compose is better or lets say more flexible, but at the same time also kinda verbose.

One argument against compose can be the use of custom attributes. E.g. if you use aurelia-i18n and would like to use the attribute-translation approach, you'd be better off using the custom-element syntax. So as you see its really all about the use-case.

EDIT:

If we really want to go down to the nitty gritty, the best argument for the custom element approach is that compose itself is actually nothing more than a custom element.

zewa666
  • 2,593
  • 17
  • 20
  • For consistency sake, I would like to move everything to one style except where it makes sense to use the other style. Bringing a new developer into a project that uses both styles willy nilly for no rhyme or reason would just take a little longer to explain that they both essentially are doing the same thing (although they don't necessarily in some cases). I find it interesting that you think using `` is more verbose; after all the imports, `@bindable` decorator, and ``, in my opinion the `` lifestyle is easier on the eyes, but maybe I am alone on that! – Anj Aug 11 '16 at 17:29
  • Well partially, you can omit the require if you do a global registration of the component. Also clearly defined attributes might describe the purpose better instead of a object passed to the model. So as such its really just a matter of taste – zewa666 Aug 12 '16 at 13:39
1

The answer is no. You don't need to switch over for situations like the example provided. The Compose element (i.e. Components) and Custom Elements solve different problems. The former allows you to compose a view or view and viewmodel pair into another view. The default behavior matches up views and viewmodels based on name but I understand you could actually bind a different viewmodel each time (which might give some interesting uses in say, a for loop.) I use Components when I want to break a larger view down into more manageable chunks. I will also use them where I want code reuse, but I am not looking to customize it too much from one use to another e.g. footer, navigation.

Custom Elements I understand are basically WebComponents, an evolving web standard that takes advantage of the Shadow DOM. (You can read more about that at links below.) While similar, they have a lot more power than a simple Component and IMO a greater ability for reuse. Unlike a Component, a Custom Element can have a range of bound attributes and therefore give you more control over it as you use it in a view. The example of your teammate's doesn't really do them justice. One could argue that a Component would be a better choice in that situation.

Robb Vandaveer
  • 1,481
  • 20
  • 25
1

Another important aspect to understand between the compose element and a custom element is the life cycle that is invoked.

Using compose element will invoke the activate(params) of the Navigation Life Cycle, as well as the usual Component Life Cycle (created, bind, attached, detached, unbind).

This can be useful, and a nuance.

Tjad Clark
  • 552
  • 3
  • 17