Добавить класс к элементам для значений атрибута с помощью Backbone.ModelBinder

Я использую Backbone.ModelBinder в проекте Backbone.js Marionette. У меня есть сценарий, который я не могу понять, как использовать ModelBinder для автоматического обновления моей модели / пользовательского интерфейса.

Моя модель имеет строковый атрибут status с несколькими состояниями. В этом примере я покажу код для двоих: "скоро", "когда-нибудь"

В моем пользовательском интерфейсе есть список, в котором я использую события щелчка, чтобы установить состояние модели, и обновляю классы, чтобы выделить соответствующую ссылку в пользовательском интерфейсе.

<dd id="status-soon"><a>Soon</a></dd>
<dd id="status-someday" class="active"><a>Someday</a></dd>

events: {
    'click #status-soon': 'setStatusSoon',
    'click #status-someday': 'setStatusSomeday'
},
setStatusSoon: function () {
    this.model.set('status', 'soon');
    this.$el.find('.status dd').removeClass('active');
    this.$el.find('#status-soon').addClass('active');
},
... etc

Такое чувство, что я делаю это многословно и неуклюже! Раздувание кода увеличивается с количеством состояний, которые мне нужно поддерживать. Каков наилучший способ достижения того же результата с ModelBinder?

3 ответа

Решение

Возможно, вы могли бы упростить вещи с помощью атрибута данных, что-то вроде этого:

<dd data-status="soon" class="set-status"><a>Soon</a></dd>
<dd data-status="someday" class="set-status active"><a>Someday</a></dd>

а потом:

events: {
    'click .set-status': 'setStatus'
},
setStatus: function(ev) {
    var $target = $(ev.target);
    var status  = $target.data('status');
    this.model.set('status', status);
    this.$el.find('.status dd.set-status').removeClass('active');
    $target.addClass('active');
}

Вам может не понадобиться set-status класс, просто набирая вещи на <dd>s может быть достаточно; Я предпочитаю отделить обработку событий от мельчайших деталей.

К сожалению, будет довольно сложно сделать именно то, что вы хотите с ModelBinder, Основная причина в том, что ModelBinder хочет предоставить одинаковое значение для всех элементов, которые являются частью одного селектора. Так делать это с ModelBinder, хотя возможно, будет довольно многословным, а также.

Очистка, предлагаемая mu, вероятно, будет лучше, чем попытка использовать ModelBinder, 1) потому что вам нужен обработчик кликов, чтобы сделать this.model.set независимо от того, что и 2) вам понадобятся отдельные привязки для ModelBinder потому что функция преобразователя вызывается один раз для одного селектора, а затем устанавливается значение для всех совпадающих элементов (вместо циклического перебора каждого из них).

Но если вы хотите попробовать что-то сделать с ModelBinder это будет выглядеть примерно так:

  onRender : function () {
    var converter = function (direction, value) { 
      return (value == "soon" ? "active" : "");
    };
    var bindings = {
      status : {selector : "#status-soon", elAttribute : "class", converter : converter}
    };
    this.modelBinder.bind(this.model, this.el, bindings);
  }

Это будет делать то, что вы хотите. Конечно, как я уже говорил выше, недостатком является то, что вам потребуются привязки нескольких селекторов. Вы можете обобщить конвертер используя this.boundEls[0] но вам все равно понадобятся отдельные привязки, чтобы он работал.

Если вы хотите получить доступ к связанному элементу, можно объявить html как elAttrbute, изменить элемент и вернуть его html с помощью функции преобразователя:

onRender : function () {
  var converter = function (direction, value, attribute, model, els) {
    return $(els[0]).toggleClass('active', value === 'soon').html();
  };
  var bindings = {
    status : {
      selector : "#status-soon", 
      elAttribute : "html", 
      converter : converter
    }
  };
  this.modelBinder.bind(this.model, this.el, bindings);
}
Другие вопросы по тегам