Dynamically select runtime views using Ember + Handlebars

I use Ember, Ember Data and Handlebars to display a timeline with several types of models. My current implementation, although functioning properly, seems to be significantly improved with an agreement and an assistant. However, I cannot figure out how to use the already defined patterns.

This is what I have:

{{#view App.AccountSelectedView contentBinding="App.selectedAccountController.everythingSorted"}}
  {{#with content}}
    <ol class="timeline">
      {{#each this}}
        {{#is constructor="App.Design"}}
        ... stuff about the design
        {{/is}}
        {{#is constructor="App.Order"}}
        ... stuff about the order
        {{/is}}
        {{#is constructor="App.Message"}}
        ... stuff about the message
        {{/is}}
      {{/each}}
    </ol>
  {{/with}}
{{/view}}

... along with an assistant ...

Handlebars.registerHelper('is', function(options) {
  if (this.constructor == options.hash["constructor"]) {
    return options.fn(this);
  }
});

I would rather rely on some kind of agreement to figure out what kind of rendering. For instance:

<script type="text/x-handlebars-template" data-model="App.Design" id="design-view">
... stuff about the design
</script>

<script type="text/x-handlebars-template" data-model="App.Order" id="order-view">
... stuff about the order
</script>

Perhaps the data-model attribute can be used to determine how the object is rendered.

{{#view App.SelectedAccountView contentBinding="App.selectedAccountController.everythingSorted"}}
  {{#with content}}
    <ol class="timeline">
      {{#each this}}
        {{viewish this}}
      {{/each}}
    </ol>
  {{/with}}
{{/view}}

Alas, I can’t understand how to access the templates from the assistant.

Handlebars.registerHelper('viewish', function(options) {
   // Were I able to access the templates this question
   // would be unnecessary.
   // Handlebars.TEMPLATES is undefined...
});

Also, is this something I should do with Handlebars?

+5
4
+5

, , mixin. . , App.Design App.DesignView.

App.ViewTypeConvention = Ember.Mixin.create({
  viewType: function() {
    return Em.getPath(this.get('constructor') + 'View');
  }.property().cacheable()
});

...

App.Design.reopen(App.ViewTypeConvention);
App.Order.reopen(App.ViewTypeConvention);

... :

{{#each content}}
  {{view item.viewType tagName="li" contentBinding="this"}}
{{/each}}

, . , . "" .

+4

: / . . DesignView, OrderView .. templateName ( coffeescript):

App.DesignView = Em.View.extend
  templateName: 'design'

App.OrderView = Em.View.extend
  templateName: 'order'

/.

, , . viewType .

App.Design = Em.Model.extend
  viewType: App.DesignView

App.Order = Em.Model.extend
  viewType: App.OrderView

:

{{#collection contentBinding="App.selectedAccountController.everythingSorted"}}
  {{view content.viewType contentBinding="content"}}
{{/collection}}

, , , . factory . , :

App.selectedAccountController = Em.ArrayController.create
  ..
  viewForModel: (model) ->
    # if model is instance of Design return DesignView, Order return OrderView etc.
  everythingSortedWithViews: ( ->
    everythingSorted.map (model) ->
      {model: model, viewType: @viewForModel(model)}
  ).property('everythingSorted')

:

{{#collection contentBinding="App.selectedAccountController.everythingSortedWithView"}}
  {{view content.viewType contentBinding="content.model"}}
{{/collection}}

, , . , -, , .

+1

, .

'page' hasMany 'activity'.

// App.PageModel
export default DS.Model.extend({
    index     : DS.attr('number'),
    activity  : DS.hasMany('activity',  { async: true })
});

"activity" "type", , .

// App.ActivityModel
export default DS.Model.extend({
    activityId    : DS.attr('string'),
    type          : DS.attr('string'),
    page          : DS.belongsTo('page', { async: true }),
    configuration : DS.attr()
});

. . Ember-Data.Model-Fragments.

:

{{! page.hbs }}
{{#with activity}}
    {{#each}}
        {{partial type}}
    {{/each}}
{{/with}}

: 'static', {{{3 }}} html.

{{! static.hbs }}
{{{configuration.content}}}

, "". ..: : 'multiplechoice',

{{! multiplechoice.hbs }}
{{#with configuration}}
    {{#each options}}
    <label {{bind-attr class=":label selected:checked:unchecked"}}>
        {{view Ember.Checkbox checkedBinding="selected" }}
        {{#if text.content}}
            {{{text.content}}}
        {{else}}
            {{text}}
        {{/if}}
    </label>
    {{/each}}
    {{ ...etc... }}
{{/with}}

With partial, do not forget to consider the nomenclature and / or folder structure depending on your environment, that is, "_partialname.hbs" or "viewname / partialname.hbs"

+1
source

All Articles