KnockoutJS - Добавление вычисляемых значений в наблюдаемый массив - PullRequest
6 голосов
/ 23 февраля 2012

Я связываю данные со страницей, используя KnockoutJS, ViewModel заполняется JSON-ответом на вызов AJAX с использованием подключаемого модуля mapping , например:

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

Средняя часть там не работает (она прекрасно работает без этого вычисляемого свойства). «Brokers» - это наблюдаемый массив, и я хочу добавить вычисленное значение к каждому элементу в массиве с именем URL. Я связываю этот массив Brokers с foreach, и я хотел бы использовать этот URL в качестве атрибута href якоря. Есть идеи?

Ответы [ 3 ]

13 голосов
/ 05 февраля 2013

Я работал над очень похожими проблемами и обнаружил, что вы можете перехватить создание объектов Broker и вставить свои собственные поля, используя параметр параметров отображения:

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

Вотскрипка, чтобы продемонстрировать это: http://jsfiddle.net/pwiles/ZP2pg/

12 голосов
/ 23 февраля 2012

Ну, если вы хотите, чтобы Url был у каждого брокера, вы должны добавить его к каждому брокеру:

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

Я думаю, BrokerNum не изменится, так что вы можете просто рассчитать URL один раз:

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

Вы также можете добавить свойство Url во время отображения, предоставив обратный вызов create для функции ko.mapping.fromJS.Подробности смотрите в mapping plugin docs .

Если вам нужен только URL для привязки к href, просто привяжите выражение в html (в рамках привязки foreach):

<a data-bind="attr: {href: 'BASEURLHERE/' + BrokerNum()}">link to broker details</a>
0 голосов
/ 30 января 2014

Благодаря Питеру Уайлсу у меня очень похожее решение:

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

Некоторые отличия: Я не привязываюсь к себе, но к этому. Продукту. Входной JSON не имеет родительского имени, как «Brokers» в приведенном выше примере:

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

Итак, в productMapping я набираю просто 'create:'

Но что я не понимаю, так это структура функции создания. Может кто-нибудь объяснить мне, почему функция возвращает новую функцию, которая имеет свойство. Разве это не может быть как-то упрощено?

...