NocauteJS:Adicionando propriedades e funções observáveis ​​a objetos em um ObservableArray gerado por mapeamento

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

Pergunta

eu sou novo Knockout JS, e estou tentando adicionar propriedades e métodos adicionais aos objetos gerados no ko.observableArray() conforme criado pelo mapping plugar.


É aqui que estou indo:

  • Eu tenho uma matriz JSON de Users
  • Eu criei o ko.observableArray() com o plugin de mapeamento
  • Eu tenho um modelo que cria linhas de tabela para cada User, até aí tudo bem :o)


Aqui está o que estou tentando fazer:

Cada User tem uma propriedade chamada 'IsActive' - Eu gostaria de data-bind um evento de clique para um método em cada User objeto que alterna isso 'IsActive' propriedade.

Esta pergunta parecia promissora, mas me parece uma duplicação desnecessária ter que declarar todo o View Model em JS (a menos que seja assim que eu tenho que fazer!) - é possível apenas estender o objeto gerado?

Eu estava pensando mais nesse sentido, onde há uma maneira de declarar propriedades ou métodos adicionais e fazer com que eles estendam o mapping objetos gerados, mas este artigo se preocupa com objetos únicos em vez de estender objetos em uma matriz gerada.


Aqui está o código: http://jsfiddle.net/yZkSf/2/ (ainda não estou trabalhando no violino JS - mas continuarei brincando com ele e atualizarei este link quando começar a funcionar).

obrigado pela ajuda

Foi útil?

Solução

Existem várias opções que você pode considerar.

-Uma é usar o create ligar de volta para controlar como seus objetos "usuário" são criados.Você mesmo pode definir os observáveis ​​e adicionar funcionalidade extra ou chamar o plug-in de mapeamento no objeto de usuário individual e adicionar funcionalidade extra.

Seria algo como: http://jsfiddle.net/rniemeyer/fkVaK/

-Caso contrário, você pode colocar a função "toggle" no seu viewModel e depois passar o objeto "user" para ele.

Uma boa maneira com 1.3 é usar ko.dataFor junto com algo como a funcionalidade de delegação de eventos live/delegate/on do jQuery.Seria como: http://jsfiddle.net/rniemeyer/FkjNr/

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

Se não quiser usar a delegação de eventos, você pode passar o item diretamente usando uma função anônima como: http://jsfiddle.net/rniemeyer/GpQtN/

EDITAR:a partir da versão 2.0, os dados atuais são passados ​​automaticamente para o manipulador ao usar ligações de clique/evento, então você pode simplesmente fazer:

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

Outras dicas

Isso é o que eu descobri usando as respostas suas e de Ryan ... parece funcionar.Deixe um feedback, pois sou novo no Knockout e estou curioso para saber se essa é uma boa abordagem.

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 -->

Eu encontrei uma maneira de fazer isso, mas significa fazer um loop pelos objetos gerados no array, uma vez que eles foram criados .. Eu prefiro uma maneira de obter o mesmo resultado sem o loop adicional.

EDITAR: Como RP Niemeyer sugere em sua resposta! ; o)

De qualquer forma, uma maneira de adicionar propriedades a um objeto existente é usar jQuery extend () para combinar os objetos.

Primeiro, declare as propriedades e funções extras em um novo objeto:

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

Então, após a chamada ko.mapping.fromJS(), mas antes da chamada ko.applyBindings() , faça um loop pelos objetos na matriz gerada e estenda-os:

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

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

ko.applyBindings(viewModel);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top