2012-02-22 7 views
6

Jestem wiązania danych na stronie za pomocą KnockoutJS, ViewModel jest wypełniana przez odpowiedzi JSON z wywołania AJAX przy użyciu mapping plugin coś takiego:KnockoutJS - Dodawanie obliczonych wartości obserwowanej tablicy

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

Środkowa część nie działa (działa dobrze bez obliczonej właściwości). "Brokery" to tablica obserwowalna i chcę dodać obliczoną wartość do każdego elementu w tablicy o nazwie URL. Wiążę tę tablicę Brokerów z foreach i chciałbym użyć tego adresu URL jako atrybutu zakotwiczenia href. Jakieś pomysły?

Odpowiedz

12

Cóż, jeśli chcesz URL w każdym maklera, trzeba dodać ją do każdego Broker:

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

Chyba BrokerNum nie ulegnie zmianie, więc równie dobrze można po prostu obliczyć Url raz:

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

Możesz również dodać właściwość Url podczas mapowania, zapewniając wywołanie zwrotne "create" dla funkcji ko.mapping.fromJS. Aby uzyskać szczegółowe informacje, patrz mapping plugin docs.

Jeśli trzeba tylko url do związania href, po prostu związać wyraz w html (w foreach wiązania):

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

Pracuję przez bardzo podobnych zagadnień i odkryłem, że można przechwycić tworzenia obiektów Broker i wstawić własne pola za pomocą parametru opcji mapowania:

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

Oto skrzypce zademonstrować: http://jsfiddle.net/pwiles/ZP2pg/

+0

To podejście działa jak urok! – Tobscher

0

Dzięki Peter Wiles mam bardzo podobne rozwiązanie:

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

pewne różnice: nie jestem mapowania do siebie, ale na this.product. JSON wejście ma nie nadrzędnej nazwy jak „Brokers” w powyższym przykładzie:

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

Więc productMapping piszę tylko „stworzenie:”

Ale, co nie rozumiem jest struktura stworzyć funkcję. Czy ktoś mógłby mi wyjaśnić, dlaczego funkcja zwraca nową funkcję, która ma właściwość. Czy nie można go w jakiś sposób uprościć?