Reputation: 3325
I'm trying to figure out how to do something incredibly simple: Use conditionals in templates with data fetched with getJSON. I need to show info based on the type
key on the JSON hash. As an example, I've included a HBS file of what'd I'd like to do. What is the Ember Way™ to accomplish this?
Company route:
// routes/company.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function(params) {
return this.store.findRecord('company', params.company_slug);
},
setupController: function(controller, model) {
this._super(controller, model);
Ember.$.getJSON('/companies/%@/events.json'.fmt(model.get('slug'))).then(data => {
controller.set('events', data);
});
}
});
Company show template with example of what I'd like to do:
<ul class="test">
<li>lol</li>
{{#each events as |event|}}
<li class="{{event.type}}">
{{event.title}}
{{!-- This code will obviously not work: --}}
{{#if event.type == 'company_event'}}
show company event stuff
{{/if}}
{{#if event.type == 'user_event'}}
show user event stuff
{{/if}}
</li>
{{/each}}
</ul>
Example of JSON data:
[
{
title: "test test test",
type: "company_event",
date: "2015-10-14T00:00:00.000+02:00"
}
]
Upvotes: 0
Views: 160
Reputation:
Define event
as an Ember object so you can define computed properties on it:
var eventObject = Ember.Object.extend({
isCompanyEvent: Ember.computed.equal('type', 'company_event')
});
When reading in events, build Ember objects:
Ember.$.getJSON('/companies/%@/events.json'.fmt(model.get('slug'))) .
then(data => controller.set('events', data.map(event =>
eventObject.create(event)));
Then
{{#if event.isCompanyEvent}}
show company event stuff
The developers of Mustache and Handlebars had a clear philosophical perspective that business logic--which they defined broadly--did not belong in templates. Their notion was "you prepare the data, I pump it out". Their objective was first to keep templates simple and readable, but more importantly to keep business rules in one place--most commonly in the equivalent of the controller. For instance, the fact that the type
property of the event
object has a possible value of "company_event"
which has some particular semantics is, in this view, a variety of business logic, and thus does not belong in the template, whose job is crank out some HTML. To put it a different way, these developers wanted to avoid a situation where every single change to an interface required changing n different things in n different places. Certainly, no developer wants to go spelunking through templates to find places where various manifest constants are used to mean magic things. The problem is all the more relevant since whereas with JS code we can easily add logic, in the model, controller, or object, to detect and report on invalid values for fields such as type
, it is harder, and in practice not common, for programmers to add such error-detection logic to templates; and if they do, it's hard to direct the error output anywhere meaningful. To put it a different way, templates have no equivalent of assert
.
Which is all a very long-winded way of saying, things like ember-truth-helpers
are a horrible idea. Two steps forward, one step back. More than a decade after people started separating logic and content using templates, logic is surreptitiously creeping back into content with the connivance of things like the new style of Ember helpers which permit things like {{#if (eq
.
Upvotes: 2
Reputation: 6577
There are two suggestions I can think of:
{{#if (eq event.type 'company_event')}}
show company event stuff
{{/if}}
{{component}}
You would have a company_event
and a user_event
component (you would need to dasherize the names to comply with the naming rules), and do something like:
{{component event.type event}}
Another possibility with components is to wrap the whole thing in a component and use computed properties:
{{#each events as |event|}}
{{li-event event=event}}
{{/each}}
// components/li-event.js
export default Ember.Component.extend({
tagName: "li",
classNameBindings: ['event.type'],
isCompanyEvent: Ember.computed.equal('event.type', 'company_event'),
isUserEvent: Ember.computed.equal('event.type', 'user_event')
});
// templates/components/li-event.js
{{event.title}}
{{#if isCompanyEvent}}
show company event stuff
{{/if}}
{{#if isUserEvent}}
show user event stuff
{{/if}}
Which option to choose is left as an exercise for the reader ;)
Upvotes: 1