Модель вложенного представления нокаута
Я застрял в том, что должно быть простым решением. Я использую knockout.js с вложенными моделями просмотров, и все кажется прекрасным, за исключением того, что моя функция удаления работает неправильно. Кажется, что он привязан правильно, однако он не запускается, когда я нажимаю remove.
Почему вложенные модели просмотра? Длинная история, но, по сути, много вещей должно быть на одной странице!
Итак, вот код:
HTML
<section class="mini-form-container">
<form data-bind="submit: repeatGuest.addDate">
<input type="date" data-bind="value: repeatGuest.previousStay"/>
<button type="submit" class="button-secondary ">Add date</button>
</form>
<div data-bind="foreach: repeatGuest.dates, visible: repeatGuest.dates().length > 0">
<div>
<input data-bind="value: date" disabled="disabled" />
<a data-bind="click: $parent.removeDate">Remove</a>
</div>
</div>
</section>
<section>
<div data-bind="text: ko.toJSON($data)"></div>
</section>
Javascript
function RepeatGuest() {
/// <summary>Child View Model</summary>
this.dates = ko.observableArray();
this.previousStay = ko.observable();
}
RepeatGuest.prototype.addDate = function () {
var self = this.repeatGuest;
if (self.previousStay()) {
self.dates.push({
date: self.previousStay()
});
}
};
RepeatGuest.prototype.removeDate = function (date) {
this.dates.remove(date);
}
function ViewModel() {
var self = this;
self.repeatGuest = new RepeatGuest();
}
ko.applyBindings(new ViewModel());
И вот моя скрипка: http://jsfiddle.net/6Px4M/2/
Итак, почему моя функция удаления не запускается?
Возможный побочный вопрос: вложенные модели представлений - это неправильный путь для нокаута, здесь, похоже, не так много информации?
Ответы
Ответ 1
Одним из лучших способов работы с вложенной моделью является использование привязки with
. Вы можете сделать:
<div data-bind="with: repeatGuest">
...
</div>
Теперь область видимости - это repeatGuest
, и вы можете напрямую связываться с ее свойствами.
Проблема с вашей функцией remove
связана со значением this
и кем $parent
является в то время. Функции выполняются со значением this
, равным текущей области. Когда ваша функция удаления привязана, область видимости является одним из объектов массива date
.
Обычно для этого нужно убедиться, что ваша функция всегда должна использовать правильное значение this
. Это можно сделать в привязке (очень некрасиво), например:
<a data-bind="click: $parent.repeatGuest.removeDate.bind($parent.repeatGuest)">Remove</a>
Лучше всего связать его в модели представления в конструкторе repeatGuest
:
this.removeDate = this.removeDate.bind(this);
Это позволяет реализации реализовать прототип и перезаписывать его на каждом экземпляре с помощью обертки, которая заставляет правильное значение this
. Кроме того, если вы не поместите его в прототип, вы можете использовать шаблон var self = this;
и использовать self
в обработчике.
http://jsfiddle.net/cNdJj/
Ответ 2
Связывание не будет обращаться к функции на неправильном прототипе. Вы привязываетесь к viewModel, а не к объекту RepeatGuest прямо сейчас.
Он работает, если вы установите его как локальную функцию:
http://jsfiddle.net/6Px4M/3/
function ViewModel() {
var self = this;
self.repeatGuest = new RepeatGuest();
self.removeDate = function (date) {
self.repeatguest.dates.remove(date);
}
}