0
votes

I'd like to iterate over a class variable array in Handlebars in ember-cli to generate a list of checkboxes (categories), with the appropriate ones checked off based on which categories the model belongs to.

I have several issues: - I can't figure out how to access the class variable in ember-cli. I've seen tutorials showing that in ember.js, it's just App.Listing.CATEGORIES, but I'm not getting any passes through my each loop. - How to check off the appropriate box? I have some janky code below that probably doesn't work.

listing.js:

import DS from "ember-data";

var Listing = DS.Model.extend({
    categories: DS.attr(), // string array
});

Listing.reopenClass({
    CATEGORIES: ['park', 'outdoors']
});

export default Listing;

show.hbs:

<ul>
{{#each category in CATEGORIES}}
<li>{{input type="checkbox" name=category checked=categories.contains(category)}} {{category}}</li>

{{/each}}
</ul>
1

1 Answers

1
votes

Handlebars templates can’t look up classes like that, nor does complex logic like categories.contains(category) work. You’ll need to add a computed property to the controller or component to supply proxy objects to the template. Assuming it’s a controller, here’s a rough example:

export default Ember.Controller.extend({
  selectableCategories: function() {
    var model = this.get('model');

    return model.constructor.CATEGORIES.map(function(category) {
      var categoryProxy = Ember.Object.create({
        model: model,
        name: category,
        checked: function(key, value) {
          var model = this.get('model');

          // setter; the checkbox value has changed
          if (arguments.length > 1) {
            if (model.get('categories').contains(this.get('name'))) {
              model.get('categories').removeObject(this.get('name'));
            }
            else {
              model.get('categories').addObject(this.get('name'));
            }
          }

          // getter; the template is checking whether the checkbox should be checked
          return model.get('categories').contains(this.get('name'));
        }.property('model.categories')
      });

      return categoryProxy;
    });
  }.property('model.categories')
});

The selectableCategories computed property returns an array of objects that observe the model’s categories attribute and represent whether or not each category is found within it.

Then in your template, you can use the proxy objects like this:

{{#each category in selectableCategories}}
  {{input type="checkbox" name=category.name checked=category.checked}} {{category.name}}
{{/each}}