KnockoutJS: добавление наблюдаемых свойств и функций к объектам в сгенерированном отображении ObservableArray - PullRequest
17 голосов
/ 06 декабря 2011

Я новичок в KnockoutJS , и я застрял, пытаясь добавить дополнительные свойства и методы к сгенерированным объектам в ko.observableArray(), созданным плагином mapping.


Вот где я до:

  • У меня есть массив JSON Users
  • Я создал ko.observableArray() с подключаемым модулем
  • У меня есть шаблон, который создает строку таблицы для каждого User, пока все хорошо: o)


Вот что я пытаюсь сделать:

Каждый User имеет свойство с именем 'IsActive' - я бы хотел data-bind событие щелчка для метода для каждого User объекта, который переключает это 'IsActive' свойство.

Этот вопрос выглядел многообещающе , но мне кажется ненужным дублирование, чтобы мне пришлось объявлять всю модель представления в JS (если это не так, как я должен это делать!) - возможно ли просто расширить созданный объект?

Я больше думал об этом , где есть способ объявить дополнительные свойства или методы и попросить их расширить сгенерированные объекты mapping, но эта статья посвящена отдельным объектам, а не расширению объекты в сгенерированном массиве.


Вот код: http://jsfiddle.net/yZkSf/2/ (еще не работает в скрипте JS - но я продолжу играть с ним и обновлю эту ссылку, когда я его заработаю).

Спасибо за вашу помощь

Ответы [ 3 ]

13 голосов
/ 06 декабря 2011

Есть несколько вариантов, которые вы могли бы рассмотреть.

-Один использовать обратный вызов create для управления созданием ваших "пользовательских" объектов.Вы можете сами определить наблюдаемые и добавить дополнительную функциональность или вызвать подключаемый модуль сопоставления для отдельного пользовательского объекта, а затем добавить дополнительную функциональность.

Будет что-то вроде: http://jsfiddle.net/rniemeyer/fkVaK/

-В противном случаеВы можете поместить функцию «toggle» в viewModel, а затем передать ему объект «user».

Хороший способ с 1.3 - использовать ko.dataFor вместе с чем-то вроде live / делегат / on jQuery.Функциональность делегирования событий.Будет выглядеть так: http://jsfiddle.net/rniemeyer/FkjNr/

//unobtrusive event handler
$(".toggle").live("click", function() {
    var user = ko.dataFor(this);
    if (user) {
       viewModel.toggleIsActive(user);
    }
});

Если вы не хотите использовать делегирование событий, вы можете передать элемент напрямую, используя анонимную функцию, такую ​​как: http://jsfiddle.net/rniemeyer/GpQtN/

EDIT: начиная с 2.0 текущие данные автоматически передаются в обработчик при использовании привязок клика / события, поэтому вы можете просто сделать:

<a href="#" data-bind="click: $root.toggleIsActive"><span data-bind="text: IsActive"></span></a>
4 голосов
/ 27 июня 2012

Это то, что я придумал, используя ответы как твоего, так и Райана ... похоже, работает. Пожалуйста, оставьте отзыв, так как я новичок в Knockout и мне любопытно, если это хороший подход.

JS:

$(function() {
    $.get("users/getUsers", function(r){
        var vm = ko.mapping.fromJS(r, {
            users: {
                create: function(user){
                    var methods = {
                        toggleIsActive: function(u){u.IsActive(!u.IsActive());},
                        foo: function(u){console.log(u);},
                        bar: function(u){/*whatever*/},   
                    }
                    return $.extend(ko.mapping.fromJS(user.data), methods);
                }
            }
        });
        ko.applyBindings(vm);
    }, 'json');
});

DOM:

<!-- ko foreach: users -->
   <a href="#" data-bind="click: toggleIsActive"><span data-bind="text: IsActive"></span></a>
<!-- /ko -->
0 голосов
/ 06 декабря 2011

Я нашел способ сделать это, но это означает циклический просмотр сгенерированных объектов в массиве после того, как они были созданы. Я бы предпочел способ достичь того же результата без дополнительного цикла.

РЕДАКТИРОВАТЬ: Как Р.П. Нимейер предлагает в своем ответе! ; o)

В любом случае, один из способов добавить свойства в существующий объект - это использовать jQuery extend () для объединения объектов.

Сначала объявите дополнительные свойства и функции в новом объекте:

var userModel = {
    toggleIsActive: function() {
        console.log('toggleIsActive called: before: ' + this.IsActive());
        this.IsActive(!this.IsActive());
        // todo: save!
        console.log('toggleIsActive called: after: ' + this.IsActive());
    }
}

Затем, после вызова ko.mapping.fromJS(), но перед вызовом ko.applyBindings() выполните цикл по объектам в сгенерированном массиве и расширьте их:

viewModel.users = ko.mapping.fromJSON(/* get JSON */);

for (var i = 0; i < viewModel.users().length; i++) {
    $.extend(viewModel.users()[i], userModel);
}

ko.applyBindings(viewModel);
...