2012-02-22 17 views
6

sto associazione dati a una pagina utilizzando KnockoutJS, il ViewModel sta compilando da una risposta JSON da una chiamata AJAX usando l'mapping plugin, in questo modo:KnockoutJS - Aggiunta valori calcolati a una matrice osservabile

$(function() { 
    $.getJSON("@Url.Action("Get")", 
     function(allData) { 
      viewModel = ko.mapping.fromJS(allData); 

      viewModel.Brokers.Url = ko.computed(function() 
      { 
       return 'BASEURLHERE/' + this.BrokerNum(); 
      }); 

      ko.applyBindings(viewModel); 
    }); 
}); 

La parte centrale non funziona (funziona bene senza quella proprietà calcolata). "Broker" è un array osservabile e voglio aggiungere un valore calcolato a ogni elemento dell'array chiamato URL. Sono vincolante per l'associazione di Broker a un foreach e mi piacerebbe utilizzare quell'URL come attributo href di un ancoraggio. Qualche idea?

risposta

12

Beh, se si vuole URL in ogni broker, si deve aggiungere a ogni broker:

$.each(viewModel.Brokers(), function(index, broker){ 
    broker.Url = ko.computed(function(){return 'BASEURLHERE/' + broker.BrokerNum();}); 
}); 

Credo BrokerNum non sta per cambiare, quindi si potrebbe anche solo calcolare Url volta:

$.each(viewModel.Brokers(), function(index, broker){ 
    broker.Url = 'BASEURLHERE/' + broker.BrokerNum(); 
}); 

È inoltre possibile aggiungere la proprietà Url durante la mappatura fornendo il callback "crea" alla funzione ko.mapping.fromJS. Vedere mapping plugin docs per i dettagli.

Se avete solo bisogno url di legarsi a href, basta legare l'espressione in html (entro foreach vincolante):

<a data-bind="attr: {href: 'BASEURLHERE/' + BrokerNum()}">link to broker details</a> 
11

Ho lavorato con problemi molto simili e ho scoperto che si può intercettare la creazione degli oggetti broker e inserire i propri campi utilizzando il parametro opzioni di mappatura:

var data = { "Brokers":[{"BrokerNum": "2"},{"BrokerNum": "10"}] }; 

var mappingOptions = { 
    'Brokers': { 
     create: function(options) { 
      return (new (function() { 
       this.Url = ko.computed(function() { 
        return 'http://BASEURLHERE/' + this.BrokerNum(); 
       }, this); 

       ko.mapping.fromJS(options.data, {}, this); // continue the std mapping 
      })()); 
     } 
    } 
}; 

viewModel = ko.mapping.fromJS(data, mappingOptions); 

ko.applyBindings(viewModel); 

Qui è un violino per dimostrare questo: http://jsfiddle.net/pwiles/ZP2pg/

+0

Questo approccio funziona come un fascino! – Tobscher

0

Grazie a Peter Wiles ho soluzione molto simile:

var ViewModel = function (data, ranges) { 
    var self = this; 

    this.productList = ko.observableArray(); 
    var productListMapping = { 
     create: function (options) { 
      return (new (function() { 
      //this row above i don't understand... 
       this.len = ko.computed(function() { 
        //just test function returning lenght of object name 
        // and one property of this model 
        return this.name().length + ' ' + self.cons_slider_1(); 
       }, this); 

       ko.mapping.fromJS(options.data, {}, this); // continue the std mapping 
      })()); 
     } 
    } 

    this.cons_slider_1 = ko.observable(100); 

    ko.mapping.fromJS(data, productListMapping, this.productList); 
}; 

Alcune differenze: non sto mappatura per sé, ma su this.product. JSON ingresso ha nome non genitore come 'Brokers' nel precedente Esempio:

var products = [ 
    { "id": "pp1", "name": "Blue windy" }, 
    { "id": "pp1", "name": "Blue windy" }]; 

Così in productMapping sto scrivendo solo 'creare:'

Ma, quello che non capisco è la struttura del creare una funzione. Qualcuno potrebbe spiegarmi perché la funzione restituisca una nuova funzione, che ha proprietà. Non potrebbe essere semplificato in qualche modo?

Problemi correlati