Добавить класс к элементам для значений атрибута с помощью 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);
}