KnockoutJS: aggiunta di proprietà e funzioni osservabili agli oggetti in un ObservableArray generato dalla mappatura

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

Domanda

Sono nuovo su KnockoutJS e sono bloccato nel tentativo di aggiungere ulteriori proprietà e metodi agli oggetti generati nel ko.observableArray() come creato dal plug-in mapping.


Ecco dove sto andando:

  • Ho un array JSON di Users
  • Ho creato ko.observableArray() con il plug-in di mappatura
  • Ho un modello che crea una riga di tabella per ogni User, finora tutto bene: o)


Ecco cosa sto cercando di fare:

Ogni User ha una proprietà chiamata 'IsActive': vorrei generare un evento click su un metodo su ogni oggetto data-bind che attiva questa proprietà User.

Questa domanda sembrava promettente , ma a me sembra una duplicazione non necessaria dover dichiarare l'intero modello di visualizzazione in JS (a meno che non sia così che devo farlo!) - è possibile estendere semplicemente l'oggetto generato?

Stavo pensando di più in questo senso , dove c'è un modo per dichiarare proprietà o metodi aggiuntivi e farli estendere gli oggetti generati da 'IsActive', ma questo articolo si occupa di singoli oggetti piuttosto che di estendere oggetti in un array generato.


Ecco il codice:
http://jsfiddle.net/yZkSf/2/ (non funziona ancora con JS fiddle, ma continuerò a giocarci e aggiornerò questo collegamento quando lo farò funzionare).

Grazie per il tuo aiuto

È stato utile?

Soluzione

Ci sono diverse opzioni che potresti considerare.

-Uno è utilizzare il create callback per controllare come il tuo "utente "gli oggetti vengono creati. Puoi definire tu stesso gli osservabili e aggiungere funzionalità extra o chiamare il plugin di mappatura sul singolo oggetto utente e quindi aggiungere funzionalità extra.

Potrebbe essere qualcosa del tipo: http://jsfiddle.net/rniemeyer/fkVaK/

-Altrimenti, puoi posizionare la funzione "toggle" sul tuo viewModel e poi passarvi l'oggetto "user".

Un bel modo con 1.3, è usare ko.dataFor insieme a qualcosa come la funzionalità di delega degli eventi live / delegate / on di jQuery. Sarebbe come: http://jsfiddle.net/rniemeyer/FkjNr/

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

Se non desideri utilizzare la delega degli eventi, puoi passare l'elemento direttamente utilizzando una funzione anonima come: http://jsfiddle.net/rniemeyer/GpQtN/

MODIFICA: a partire dalla 2.0, i dati correnti vengono automaticamente passati al gestore quando si utilizzano associazioni di clic / eventi, quindi puoi semplicemente fare:

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

Altri suggerimenti

Questo è quello che mi è venuto in mente usando sia la tua risposta che quella di Ryan ... sembra funzionare.Per favore lascia un feedback, dato che sono nuovo di Knockout e sono curioso di sapere se questo è un buon approccio.

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

Ho trovato un modo per farlo, ma significa scorrere gli oggetti generati nell'array una volta che sono stati creati .. Preferirei un modo per ottenere lo stesso risultato senza il ciclo aggiuntivo ..

EDIT: Come suggerisce RP Niemeyer nella sua risposta! ; o)

Ad ogni modo, un modo per aggiungere proprietà a un oggetto esistente è utilizzare jQuery extent () per combinare gli oggetti.

Per prima cosa, dichiara le proprietà e le funzioni extra in un nuovo oggetto:

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

Quindi, dopo la chiamata ko.mapping.fromJS(), ma prima della chiamata ko.applyBindings() , scorrere gli oggetti nell'array generato ed estenderli:

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

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

ko.applyBindings(viewModel);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top