1

In aurelia, for views I can supply an Inline template by just implementing the getViewStrategy method and returning an InlineViewStrategy in the ViewModel. But this just works for Views, not for custom elements. Is there a similar way to supply an inline template for custom elements?

Thanks

Daní
  • 355
  • 1
  • 17

2 Answers2

5

You just need to use the @inlineView decorator. Here's a gist showing this: https://gist.run/?id=1df0554fcfb51fd9ab3d60367bac1b60

import {inlineView} from 'aurelia-framework';

@inlineView('<template>Hello from the inline view</template>')
export class InlineViewCustomElement {
}
Ashley Grant
  • 10,879
  • 24
  • 36
  • That's definitely a correct answer. However I can't figure out how can I dynamically supply the template depending on the value of a bindable property. The getViewStrategy method in views is called by aurelia framework after the activate method in the pipeline, therefore, when getViewStrategy is invoked I can get the model (if view is added via compose) or the params (if the view is in a router-view). Is there any hook like getViewStrategy for custom elements? – Daní Aug 27 '16 at 09:20
  • I asked the team about this. Here is the reasoning that was given, "Basically, if we allowed that it would cause the creation of every custom element to be asynchronous. That would be a big problem for performance and complexity. So, we basically isolate that to router-view and compose (or custom elements people write to do the same thing.) If someone needed that for a custom element, I would normally recommend that they create an element with an internal view that uses compose and then handle it there." – Ashley Grant Aug 29 '16 at 20:40
  • I understand the performance consequences it can cause ans I guess that Marton Sagi answer follows team's recommendation. I just need this behavior because I'm in a project with aurelia + polymer and very often repeat.for doesn't work fine withing polymer widgets like paper-menu-button, I guess repeat.for populates the dom through the task queue and that polymer doesn't listen for changes in dom, so adding paper-item items to a paper-menu-button using a repeat.for has no the desired effect. The goal is to re-write the whole template once I have the array of items bound to the repeat.for – Daní Aug 30 '16 at 08:14
  • Things may have changed since this comment was posted. https://aurelia.io/docs/integration/polymer#data-binding uses `repeat.for` in its example of creating multiple `paper-item`s. – Bae Jul 14 '19 at 23:47
3

You can use an instance of InlineViewStrategy bound to a compose element. Here's a demo: https://gist.run/?id=4e2ec80c1010c638e908589ce3fc5067

Custom Element:

inline.js

templateChanged() ensures real dynamic behaviour for this demo (re-rendering as you type). Although, it might not be needed in all cases.

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

export class Inline {

    viewStrategy;

    @bindable({ defaultBindingMode: bindingMode.oneWay })
    template;

    @bindable({ defaultBindingMode: bindingMode.oneWay })
    displayValue;

    attached() {
        this.render();
    }

    templateChanged() {
        this.render();
    }

    render() {
        this.viewStrategy = new InlineViewStrategy(`<template>${this.template}</template>`);
    }
}

inline.html

<template>
    <compose view.bind="viewStrategy"></compose>
</template>

Usage in a view:

For example, we'd like to display a nice icon.

app.js

export class App {
    customTemplate = '<i class="fa fa-3x fa-${displayValue}"></i>';
    customValue = 'stack-overflow';
}

app.html

<template>
    <require from="./inline"></require>

    <div class="container-fluid">
      <h4 class="page-header">Inline template in custom component</h4>
      <div class="form-group">
          <label>Template:</label>
          <input class="form-control" type="text" value.bind="customTemplate" />
      </div>

      <div class="form-group">
          <label>Display Value:</label>
          <input class="form-control" type="text" value.bind="customValue" />
      </div>

      <div class="panel panel-primary">
          <div class="panel-heading">Rendered view:</div>
          <div class="panel-body">
              <inline template.bind="customTemplate" display-value.bind="customValue"></inline>
          </div>
      </div>
    </div>

</template>

Hope, this helps.

Marton Sagi
  • 1,247
  • 1
  • 8
  • 10
  • Wow!! Really awsome. I haven't used before... That definitely fits my need. Thank so much – Daní Aug 29 '16 at 13:38