Нокаутирующие:Добавление наблюдаемых свойств и функций к объектам в сгенерированном отображением observableArray

StackOverflow https://stackoverflow.com/questions/8401799

Вопрос

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


Вот чем я занимаюсь:

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


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

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

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

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


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

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

Это было полезно?

Решение

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

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

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

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

Хороший способ с версией 1.3 - использовать ko.dataFor наряду с чем-то вроде функциональности делегирования событий live/delegate/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/

РЕДАКТИРОВАТЬ:начиная с версии 2.0, текущие данные автоматически передаются обработчику при использовании привязок click/event, так что вы можете просто сделать:

<a href="#" data-bind="click: $root.toggleIsActive"><span data-bind="text: IsActive"></span></a>

Другие советы

Это то, к чему я пришел, используя ваши ответы и ответы Райана...кажется, это работает.Пожалуйста, оставьте отзыв, так как я новичок в 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');
});

дом:

<!-- ko foreach: users -->
   <a href="#" data-bind="click: toggleIsActive"><span data-bind="text: IsActive"></span></a>
<!-- /ko -->

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

РЕДАКТИРОВАТЬ: Как предполагает Р.П. Нимейер в своем ответе! ;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);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top