3
votes

I have a notification box in my Ember.js app that will change the text, styling, and buttons based on the value of a Status model. How do I switch just the view (or template) for the notification box? I don't want to transitionTo because the rest of the page shouldn't update, just that notification box.

I have a JSFiddle with a complete example. But here's the relevant parts to glance at:

The main template will render the notification bar ("statusState") and the regular view data.

<script type="text/x-handlebars" data-template-name="status">
  {{render "statusState" content}}
  <p>
  Other information not related to the status state, but still related to status goes here.
  </p>
  {{outlet}}
</script>

There's a separate template for each Status state ("pending", "ready", "finished"):

<script type="text/x-handlebars" data-template-name="status/pending">
  <div style="background-color: grey">
    The status is pending.
  </div>
</script>

<script type="text/x-handlebars" data-template-name="status/ready">
  <div style="background-color: blue">
  The status is ready.
  </div>
</script>

<script type="text/x-handlebars" data-template-name="status/finished">
  <div style="background-color: green">
    The status is finished.
  </div>
</script>

The Status object is nothing special, and belongs to the StatusController:

App.StatusRoute = Ember.Route.extend({
  model: function() {
    return App.Status.create();
  }
});

App.Status = Ember.Object.extend({
  value: 0
});

My first attempt was to change the templateName of the view whenever the Status' value changes. But this feels hacky and doesn't even seem to respond to Status value changes:

App.StatusStateView = Ember.View.extend({
  templateName: function() {
    var templateName = 'status/pending';
    var value = this.get('controller.model.value');
    if (value === 1) {
      templateName = 'status/ready';
    }
    else if (value === 2) {
      templateName = 'status/finished';
    }
    return templateName;
  }.property('controller.model.value')
});

In short, how would I change the view or template for just part of the page based on a model value that has more than 2 choices?

1
The trick is in the call to rerender in the linked example. Did that help?WiredPrairie
@MilkyWayJoe - Thanks for the link. I'll go with your solution using templateNameBinding and rerender.baalexander
@WiredPrairie - templateName wasn't even getting fired on the model change, so I couldn't call re-render. I'll try it out with using a computedProperty elsewhere and templateNameBinding. Thanks!baalexander
FYI, I updated the JSFiddle with a working example using templateNameBinding here: jsfiddle.net/baalexander/FYWTK/4baalexander

1 Answers

1
votes

Here's how I would approach this. Add boolean computed properties to the model or controller and use a single template with the {{#if }} helper. e.g.

App.Status = Ember.Object.extend({
  value: 0,
  ready: function(){
     return this.get('value') === 1;
  }.property('value'),
  finished: function(){
     return this.get('value') === 2;
  }.property('value'),
  pending: function(){
     var value = this.get('value');
     return value !== 1 && value !== 2;
  }.property('value')
});

And in a single template:

{{#if pending}}
  I'm pending
{{/if}}
{{#if ready}}
  I'm ready!
{{/if}}
{{#if finished}}
  I'm finished.
{{/if}}