A
A
Alexey Ermolaev2015-11-21 01:09:11
JavaScript
Alexey Ermolaev, 2015-11-21 01:09:11

How to change the state of a model with another model?

В проекте есть две основных модели: Meet(встреча) с некоторыми параметрами и Filter, фильтр, который должен отбирать встречи по разным параметрам. Группа всех существующих встреч - это коллекция (MeetCollection). Создаем коллекцию и отрисовываем ее на экране рендером в виде списка.
У модели Filter набор критериев, по которым пользователь хочет найти встречи. Пока он только один - день недели. Он выводится в виде селекта. Нужно чтобы по выбору дня недели в MeetCollection встреч отображались только модели, соответствующие выбранному дню.
(у обеих моделей есть свойство weekDay). Я создал в модели Filter метод filterByDay(), который отбирает модели по дню, и если день не соответствует выбранному, модель в коллекции уничтожается.
Но пока я вызывал его отдельно от представления - так как не могу понять как вызвать его по событию выбора опции. Прошу помощи у сообщества.
Модель Meet

//creating Meet model
  App.Models.Meet = Backbone.Model.extend({
    defaults : {
      date : "01.11.2015",
      weekDay : "Sunday",
      timeBegin : "12:00",
      timeEnd : "00:00",
      games : [],
      placeName : "PlayLoft Gaga",
      placeAddress : "Малая Морская, 15/7"
    },
  });
  //end//

Модель Filter
App.Models.Filter = Backbone.Model.extend({

    defaults : {
      weekDay : "Monday",
    },
         //Метод фильтрации
    filterByDay : function(collection) {  
          for(var i = 0; i < collection.models.length; i++ ) {
             if(collection.models[i].get('weekDay') != this.get('weekDay')){
                   collection.models[i].destroy();
              }      
          } 
          return ;
    }

  });

Вьюха одной встречи в коллекции:
App.Views.Meet = Backbone.View.extend({

    tagName : 'li',
    template : template('meetsTemplate'),
    initialize : function(){
      this.model.on('destroy', this.remove, this);
    },

    render : function() {
      var template = this.template(this.model.toJSON());
      this.$el.html(template);
      return this;
    },

    destroy: function() {
      this.model.destroy();
    },
    remove: function() {
      this.$el.remove();
    }

  });

Вьюха фильтра в коллекции фильтров
App.Views.Filter = Backbone.View.extend({
    tagName : 'option',
    className : 'day',
    template : template('chooseTemplate'),
    render : function() {
      var template = this.template(this.model.toJSON());
      this.$el.html(template);
      return this;
    },
    events : {
      'click' : 'change'
    },
    destroy: function() {
      this.model.destroy();
    },
    remove: function() {
      this.$el.remove();
    },
  });

Эта часть уже не актуальна
UPD: В ходе изысканий было обнаружено, что метод, который я написал для фильтрации, влияет не на всю коллекцию, какая-то часть остается(2, 3 или 4 элемента, зависит от размера коллекции).
Похоже, когда элемент коллекции уничтожается, изменяется и длина массива моделей, коллекция перерисовывается заново, и индексы элементов смещаются.
Получается, нужно уничтожать нулевой элемент каждый раз?

UPD2: Проблема с методом решилась рекурсией
Для полного понимания картины я выложил полный код на фиддл:
https://jsfiddle.net/wxuzbnf6/12/
Буду очень признателен, если кто-нибудь поможет мне заметить, что я не доглядел и подскажет как можно правильно вызвать метод модели Filter в модели Meet.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
Сергей Протько, 2015-11-21
@Fesor

Ну как бы так как вы и написали в заголовке - модель меняет модель. По сути только вьюшкам запрещено напрямую менять модель.
Варианта 2:
1) у модели для фильтров есть доступ к модели коллекции айтемов. По изменению она сама меняет коллекцию, заставляее ее изменить состояние под наше.
2) доменные или просто ивенты между моделями коллекций и фильтрами. Сложнее, но зато при должном подходе получается весьма гибко и удобно, а главное с низкой связанностью. А если еще и с доменными событиями то можно придумать еще массу прикольных штук, но я пока так не упарывался (хотя планирую поэксперементировать).

Но пока я вызывал его отдельно от представления - так как не могу понять как вызвать его по событию выбора опции.

А в чем именно проблема? Не знаете как красиво передать одну модель в другую? Используйте Dependency Injection или хотя бы Resource Registry.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question