Модель вложенного представления нокаута - программирование
Подтвердить что ты не робот

Модель вложенного представления нокаута

Я застрял в том, что должно быть простым решением. Я использую 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/

Итак, почему моя функция удаления не запускается?

Возможный побочный вопрос: вложенные модели представлений - это неправильный путь для нокаута, здесь, похоже, не так много информации?

4b9b3361

Ответ 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);
    }
}