Используя KnockBack ViewModel, есть ли способ создать вычисляемую наблюдаемую из методов базовой модели Backbone?
Используя KnockBack ViewModel, есть ли способ создать вычисляемую наблюдаемую из методов базовой модели Backbone?
В качестве примера в javascript:
var MyModel = Backbone.model.extend({
validate: function () {
return this.get('name').length < 0;
}
}),
baseModel = new MyModel({name: 'foo'}),
kbViewModel = kb.viewModel(baseModel),
modelContainer = document.querySelector('#myModel');
ko.applyBindings(kbViewModel, modelContainer);
и в разметке нокаута:
<div id="myModel">
<div data-bind="css:{'invalid': !validate()}">
<input type="text" data-bind="value: name" />
</div>
</div>
Когда я пытаюсь запустить это, я получаю сообщение об ошибке:
Unable to process binding "css: function (){return {'invalid':!validate()} }"
Message: validate is not defined
Я делаю что-то не так, или мне нужно создать наблюдаемую в ViewModel вручную?
var MyModel = Backbone.Model.extend({
validate: function () {
return this.get('name').length > 0;
}
}),
MyKBViewModel = kb.ViewModel.extend({
constructor: function (model) {
kb.ViewModel.prototype.constructor.call(this, model);
this.validate = ko.pureComputed(function () {
return this.name().length > 0;
}, this);
}
}),
baseModel = new MyModel({name: 'foo', class: 'bar'}),
kbViewModel = new MyKBViewModel(baseModel),
modelContainer = document.querySelector('#myModel');
ko.applyBindings(kbViewModel, modelContainer);
jsfiddles: без наблюдаемого, с наблюдаемым
1 ответ
Небольшая преамбула: Knockback помещает модель в MVVM, где Knockout на самом деле просто VVM. Откат также дает вам некоторую автоматическую синхронизацию между ними, что приятно. Но вам все равно нужно помнить, что модель и модель представления - это две разные части вашего приложения. Модель представления - это не просто нокаут-копия модели Bootstrap. Не помещайте части модели в модель.
Поэтому вам нужно решить, является ли валидация поведением модели представления или поведением модели. Я говорю viewmodel, потому что вы хотите использовать его в представлении. Поэтому удалите его из модели и определите вычисленное.
Однако, если вы хотите, чтобы он был частью модели, вы бы хотели определить атрибут, а не просто метод, и обработчик события модели, который обновит атрибут при изменении. Knockback покорно скопирует атрибут в модель представления, и вы можете использовать его там.
var MyModel = Backbone.Model.extend({
validate: function() {
this.set('isValid', this.get('name').length > 0);
},
initialize: function() {
this.validate();
this.on('change:name', this.validate);
}
}),
baseModel = new MyModel({
name: 'foo',
isValid: null
}),
kbViewModel = kb.viewModel(baseModel);
kbViewModel.validate = ko.observable();
modelContainer = document.querySelector('#myModel');
ko.applyBindings(kbViewModel, modelContainer);
.invalid {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.2/backbone.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockback/1.0.0/knockback.min.js"></script>
<div id="myModel">
<div data-bind="css:{'invalid': !isValid()}">
<input type="text" data-bind="value: name" />
</div>
</div>