从另一个列表生成列表时,填充一个对象的observable属性

时间:2014-12-27 19:31:02

标签: knockout.js

当我从中选择的列表是从另一个对象生成时,我试图填充一个对象的observable属性。 select的选项是$root.Rider的属性,而所选的选项是$root的属性。

如果我在select标记的绑定中使用value: selectedContract(如示例所示),则选择一个选项会更改selectedContract,但在加载时不会选择预设的selectContract。< / p>

如果我将值更改为value: payment_contract().option_value并添加optionsValue:'option_value',则会在加载时填充预设,但从选项列表中进行选择时,selectContract不会更新。

代码:

$(function () {
    ko.applyBindings(new ViewModel());
});

var ViewModel = function () {
    var self = this;
    self.selectedContract = ko.observable();
   self.rider = new Rider({
        id: 11
    });
    contract = new Contract({
        terms: 'Terms 2',
        account_id: '2',
        account_name: 'Account 2'
    });
    self.selectedContract(contract)
};

//Rider
function Rider(data) { //charge options and prepaid options are arrays of contract objects
    var self = this;

    self.id = data.id;
    self.contract_options = ko.observableArray();
    //populate contract_options for demo
    var contract = new Contract({
        terms: 'charge',
        account_id: '1',
        account_name: 'Account 1'
    });
    self.contract_options.push(contract);
    contract = new Contract({
        terms: 'charge',
        account_id: '2',
        account_name: 'Account 2'
    });
    self.contract_options.push(contract);
    contract = new Contract({
        terms: 'charge',
        account_id: '3',
        account_name: 'Account 3'
    });
    self.contract_options.push(contract);
}

function Contract(data) {
    var self = this;

    self.terms = data.terms;
    self.contract_id = data.contract_id;
    self.account_id = data.account_id;
    self.account_name = ko.observable(data.account_name);
    self.option_value = ko.computed(function () {
        return self.account_id + '|' + self.contract_id;
    });
};
<select name="contract_id_charge" data-bind="options: rider.contract_options, 
    value: selectedContract, 
    optionsText: 'account_name',
    optionsCaption: 'Select Charge'
"></select>
<div data-bind="with: selectedContract">
    <div>
        <label>Terms:</label><span data-bind="text: terms"></span>
    </div>
    <div>
        <label>Account Id:</label><span data-bind="text: account_id"></span>
    </div>
    <div>
        <label>Account Name:</label><span data-bind="text: account_name"></span>
    </div>
</div>

Sample fiddle

2 个答案:

答案 0 :(得分:1)

您的问题是您在value标记上滥用了<select>数据绑定。

使用<select>标记,options绑定指定选项列表,value数据绑定应指定一个observable来保存当前所选选项的值。

相反,你有:value: payment_contract().option_value,这是一个只读的计算;而不是一个观察到持有所选合同。如果您指定value: payment_contract,则所选合同将根据需要存储在Ride的payment_contract可观察数据中。

此外,optionValue绑定为给定选项指定应在value绑定指定的observable中存储的值。你正在使用一些基于account_id和contract_id的字符串;但是你似乎更有可能只想存储对整个Contract对象的引用;而不是字符串表示,因此可能会省略绑定。

以下`标签似乎有效:

<select name="contract_id_charge" 
    data-bind="options: rider().charge_options(), 
        value: payment_contract,
        optionsText: 'account_name',  
        optionsCaption: 'Select Charge'
    ">
</select>

答案 1 :(得分:0)

考虑到你提出这个问题有多复杂,我尽力回答。而不是使用optionsValue绑定您的选择,只需使用值绑定。然后可以将其绑定到一个可观察对象,该观察对象将填充来自charge_options的选定选项。

<select name="contract_id_charge" 
data-bind="options: contract_options(), 
    value: selectedContract, 
    optionsText: 'account_name',
    optionsCaption: 'Select Charge'
"></select>
<div data-bind="with: selectedContract">
    <div>
        <label>Terms: </label><span data-bind="text: terms"></span>
    </div>
    <div>
        <label>Account Id: </label><span data-bind="text: account_id"></span>
    </div>
    <div>
        <label>Account Name: </label><span data-bind="text: account_name"></span>
    </div>
</div>
var ViewModel = function () {
    var self = this;
    self.selectedContract = ko.observable();

    self.contract_options = ko.observableArray();

    //populate contract_options for demo
    var contract = new Contract ({
        terms: 'Terms 1',
        account_id: '1',
        account_name: 'Account 1'
    });
    self.contract_options.push(contract);
    contract = new Contract ({
        terms: 'Terms 2',
        account_id: '2',
        account_name: 'Account 2'
    });
    self.contract_options.push(contract);
    contract = new Contract ({
        terms: 'Terms 3',
        account_id: '3',
        account_name: 'Account 3'
    });
    self.contract_options.push(contract);
};

function Contract(data) {
    var self = this;

    self.terms = data.terms;
    self.contract_id = data.contract_id;
    self.account_id = data.account_id;
    self.account_name = ko.observable(data.account_name);
    self.option_value = ko.computed(function () {
        return self.account_id + '|' + self.contract_id;
    });
};

http://jsfiddle.net/x6appqz0/