Comparison-conditional 'if''s in template loop

It sounds like you’ve found a solution to your problem, but in regards to your original frustrations with the limits of the if helper, I can empathize. If you run into this issue in the future, I found that it is possible to make bound block helpers (that understand value bindings), and I’ve made a few simple generic conditionals like if-equal. Sometimes making an item controller for a handful of computed properties seems like overkill to me.

Nice workaround. I think having to do this is overkill too. Doing this…

     {{#each item in model.items}}
            {{#if item.type == 'cool type'}}
                     {{#each t in item.type}}
                              {{ build out bound html elements}}

…is so much less work than the alternatives. Sure, there’s some logic in the view code, but its really just the best solution to the problem, which is all any design pattern really is.

I’m still of the opinion that you shouldn’t be using an if structure at all here. You want a map from item.type to the component, as per my earlier suggestion, you could do this using the render statement. So the loop is simply:

{{#each model.questions}}
  {{render model.type this}}
{{/each}}

For me this gives you a more modular approach and is much clearer to read.

1 Like

I guess I’m not seeing it clearly. I think you used that approach in this previous JSbin. How would you set the input’s attributes based on the values in the obj, which also contains nested objects like the one here, and where would you bind the Action?

Ok, here’s a couple of versions illustrating how I’d probably do this, the first one uses the if structure but extracts the separate views, the second one uses the pattern that I suggested above. The only difference is that it’s using the partial helper instead of render (I hadn’t realised you can only specify the literal name of a template with render). Note that it’s the QuestionController that handles the action, this is so that you have the question available without having to pass it into the action.

Also note I didn’t include the select because, time :slight_smile:

2 Likes

+1 @opsb, below is a custom render that I wrote to get round the multiple if statements which creates needless bindings. It simply constructs the template from the model type and then calls the real render:

Ember.Handlebars.registerBoundHelper 'renderNotification', (notification, options) ->   
  template = "notifications/#{@get('event')}/#{@get('tag')}"   
  options.contexts[1]= options.contexts[0]   
  Ember.Handlebars.helpers.render.call(this, template, 'model', options)

  {{#each notification in controller}}
    {{renderNotification "notification"}}
  {{/each}}

@opsb I think I’ll have to use your approach because it allows me to build out the ‘select’ properly. The problem I ran into is that I can only bind the ‘action’ to the ‘select’ tag, which means I can not pass in the id of the selected option…

<select {{action 'answerSupplied' q.id a.id this on='change' preventDefault=false}}>

           {{#each a in q.answers}}                      
                 <option id=a.id name=q.id value=a.id>
                 {{a.text}}</option>

{{/each}}

</select>

I was hoping to keep the whole form in a single template, but it doesn’t look like that’s possible. I did try using Ember.Select but I was unable to loop through the ‘answers’ array to build out the ‘options’. Passing in my own SelectController, which would return the ‘answers’ array, also didn’t work. I couldn’t figure out how to return the correct ‘answers’ array for that specific ‘select’ question. I may try again at some point, but your approach solves the problem today.

Updated JSbin

Was there any movement on this topic? I am trying to figure out how to do something like {{#if somevar in array }}

or {{#if has-permission “some_permission” }}

There is an addon for if helpers that allows conditionals. I think you need to be running ember 1.10 though.

1 Like