2012-02-22 10 views
6

Estoy enlace de datos a una página usando KnockoutJS, el modelo de vista está siendo pobladas por una respuesta JSON de una llamada AJAX usando el mapping plugin, como este:KnockoutJS - Adición de valores calculados a una matriz observable

$(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 del medio no funciona (funciona bien sin esa propiedad calculada). "Brokers" es una matriz observable, y quiero agregar un valor calculado a cada elemento en la matriz llamada URL. Estoy vinculando ese arreglo de Brokers a un foreach, y me gustaría usar ese URL como el atributo href de un ancla. ¿Algunas ideas?

Respuesta

12

Bueno, si quieres URL en cada corredor, hay que añadir que a cada corredor:

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

supongo BrokerNum no va a cambiar, por lo que también podría simplemente calcular Url vez:

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

También puede agregar la propiedad Url durante el mapeo al proporcionar "crear" una devolución de llamada a la función ko.mapping.fromJS. Ver mapping plugin docs para más detalles.

Si sólo necesita url para unirse a href, simplemente obligar a la expresión en html (dentro de foreach vinculante):

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

He estado trabajando a través de cuestiones muy similares y he encontrado que pueda interceptar la creación de los objetos Broker e insertar sus propios campos usando el parámetro de opciones de asignación:

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

Aquí está un violín para demostrar esto: http://jsfiddle.net/pwiles/ZP2pg/

+0

¡Este enfoque funciona como un encanto! – Tobscher

0

Gracias a Peter Wiles i tienen solución muy similar:

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); 
}; 

Algunas diferencias: No estoy mapeo de uno mismo, sino en this.producto. El JSON entrada tiene nombre no padre como 'agentes' en el ejemplo anterior:

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

Así que en productMapping estoy escribiendo simplemente 'crear:'

Pero, lo que no entiendo es la estructura de crear función. ¿Podría alguien explicarme por qué la función devuelve una nueva función, que tiene propiedad? ¿No podría ser simplificado de alguna manera?

Cuestiones relacionadas