Question

I'm still trying to figure out how ember works and I want to have more info on managing multiple checkboxes in ember..
here's what I tried to do: http://jsbin.com/datojebu/2/edit
as you can see all checkboxes get selected and the checked function doesn't get called
what's the correct way of doing this?

Was it helpful?

Solution 2

Okay further to your additional questions, I've basically finished your app for you:

http://jsbin.com/datojebu/11/edit

App = Ember.Application.create();
App.ApplicationAdapter = DS.RESTAdapter.extend({
    host: '/api',
    namespace: 'fr'
});

/* router */
App.Router.map(function() {
  this.resource('animes');
});
App.AnimesRoute = Ember.Route.extend({
  model: function() {
    return this.store.find('anime');
  },
  setupController: function(controller, model) {
    this._super();
    this.store.find('genre').then(function(genres) {
      controller.set('genres', genres);
    });
    controller.set('model', model);
  }
});

/* models */
var model = DS.Model,
    attr = DS.attr,
    hasMany = DS.hasMany;

App.Genre = model.extend({
    animes: hasMany('anime', {async: true}),
    nom: attr('string')
});
App.Anime = model.extend({
    nom: attr('string'),
    parution: attr('number'),
    synopsis: attr('string'),
    likes: attr('number'),
    auteur: attr('string'),

    genres: hasMany('genre', {async: true})
});
/* controllers */
App.AnimesController = Em.ArrayController.extend({
  genres: Em.A([]),
  selectedGenreIds: Em.A([]), // a set of ids
  selectedGenres: function() {
    var genres = this.get('genres'),
        selectedGenreIds = this.get('selectedGenreIds');
    return genres.filter(function(genre) {
      return selectedGenreIds.contains(genre.get('id'));
    });
  }.property('selectedGenreIds.@each', 'genres.@each'),
  selectedAnimes: function() {
    var allAnimes = this.get('model'),
        selectedGenres = this.get('selectedGenres'),
        filteredAnimes;
    // for an anime to be shown, it has to have at
    // least one of its genres selected
    filteredAnimes = allAnimes.filter(function(anime) {
      return anime.get('genres').any(function(animeGenre) {
        return selectedGenres.contains(animeGenre);
      });
    });
    return filteredAnimes;
  }.property('model.@each', 'selectedGenres.@each', 'genres.@each')
});
App.GenreController = Em.ObjectController.extend({
  needs: ['animes'],
  isChecked: function(key, value) {
    if(arguments.length > 1) {
      // setter
      var selectedGenreIds = this.get('controllers.animes.selectedGenreIds'),
          thisId = this.get('id');
      if(!selectedGenreIds.contains(thisId) && value) {
        selectedGenreIds.addObject(thisId);
      } else {
        selectedGenreIds.removeObject(thisId);
      }
    }
    // always return the value for the getter and the setter
      return value;
  }.property('controllers.animes.selectedGenreIds')
});

/* mockjax */
var animes = [
    {
        id: 1,
        nom: 'Blah',
        parution: 2014,
        genres: [1, 3],
        synopsis: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore, eveniet, ab pariatur omnis dolor sunt alias atque voluptate neque reiciendis maiores impedit quibusdam perferendis optio ratione expedita adipisci et. Cupiditate!',
        likes: 206,
        auteur: 'Moi :p'
    }
],
genres = [
    {
        id: 1,
        nom: 'action',
        animes: []
    },
    {
        id: 2,
        nom: 'magie',
        animes: [1]
    },
    {
        id: 3,
        nom: 'amour et amitier',
        animes: []
    },
    {
        id: 4,
        nom: 'aventures',
        animes: [1]
    }
];
$.mockjax({
  url: '/api/fr/animes',
  responseTime: 750,
  responseText: {
    'animes': animes
  }
});
$.mockjax({
  url: '/api/fr/genres',
  responseTime: 750,
  responseText: {
    'genres': genres
  }
});

OTHER TIPS

Check this now. http://jsbin.com/datojebu/3/edit

  {{#each genre in genres}}
       {{input type="checkbox" name=genre.id checked=genre.isChecked}} {{genre.nom}}
  {{/each}}

you have to add genre.isChecked else same isChecked will be binded to all checkboxes.

BTW if you want to have controller for each item, you can add ItemController in the array controller. Here is another example.

/* controllers */
App.AnimesController = Ember.ArrayController.extend({
  itemController: 'anime'
});

You need to do as CodeJack said...

Once you've done that, you use bindings to "know" which one is checked. That is to say you don't need to know it yourself, you just need to bind the correct values to the right spot.

Anyway, this jsbin should alleviate your issues... notice the console gets set with the value and triggered at the correct tiems/places.

http://jsbin.com/datojebu/6/edit

App = Ember.Application.create();
App.ApplicationAdapter = DS.RESTAdapter.extend({
    host: '/api',
    namespace: 'fr'
});

/* router */
App.Router.map(function() {
  this.resource('animes');
});
App.AnimesRoute = Ember.Route.extend({
    model: function() {
        return this.store.find('anime');
    },
  setupController: function(controller, model) {
        this._super(controller, model);
        this.store.find('genre').then(function(genres){
            controller.set('genres', genres);
        });
    }
});

/* models */
var model = DS.Model,
    attr = DS.attr,
    hasMany = DS.hasMany;

App.Genre = model.extend({
    animes: hasMany('anime', {async: true}),
    nom: attr('string')
});
App.Anime = model.extend({
    nom: attr('string'),
    parution: attr('number'),
    synopsis: attr('string'),
    likes: attr('number'),
    auteur: attr('string'),

    genres: hasMany('genre', {async: true})
});
/* controllers */
App.GenreController = Em.ObjectController.extend({
  isChecked: function(key, value) {
    if(arguments.length > 1) {
      // setter
      console.log('huzzah' + this.get('id') + ' val: ' + value);      
    }
    // always return the value for the getter and the setter
    return this.get('model.isChecked');
  }.property(),
  actions: {
  click: function() {
    console.log("hi");
  }    
  }
});

/* mockjax */
var animes = [
    {
        id: 1,
        nom: 'Blah',
        parution: 2014,
        genres: [1, 3],
        synopsis: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore, eveniet, ab pariatur omnis dolor sunt alias atque voluptate neque reiciendis maiores impedit quibusdam perferendis optio ratione expedita adipisci et. Cupiditate!',
        likes: 206,
        auteur: 'Moi :p'
    }
],
genres = [
    {
        id: 1,
        nom: 'action',
        animes: []
    },
    {
        id: 2,
        nom: 'magie',
        animes: [1]
    },
    {
        id: 3,
        nom: 'amour et amitier',
        animes: []
    },
    {
        id: 4,
        nom: 'aventures',
        animes: [1]
    }
];
$.mockjax({
  url: '/api/fr/animes',
  responseTime: 750,
  responseText: {
    'animes': animes
  }
});
$.mockjax({
  url: '/api/fr/genres',
  responseTime: 750,
  responseText: {
    'genres': genres
  }
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top