2016-05-24 81 views
1

有沒有辦法將數組元素作爲輸入或選擇的值綁定?數據綁定數組元素作爲值使用敲除

事情是這樣的......

var ViewModel = function() { 
 
    var self = this; 
 

 
    self.array = ko.observableArray([undefined, undefined, undefined]); 
 

 
    self.text = ko.computed(function() { 
 
    return self.array()[0] + self.array()[1] + self.array()[2]; 
 
    }); 
 
} 
 

 
var viewModel = new ViewModel(); 
 
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<input data-bind="value: $root.array[0]" /> 
 
<input data-bind="value: $root.array[1]" /> 
 
<input data-bind="value: $root.array[2]" /> 
 
<p data-bind="text: $root.text"></p>

編輯

對不起球員,我真的很可怕,使問題,但我的問題是有點更靠譜,我的真實條目是選擇,它是一個數組的過濾器並選擇了這些值。像這樣:

var ViewModel = function() { 
 
    var self = this; 
 
    self.family = ko.mapping.fromJS(data.family); 
 

 
    self.array = ko.observableArray([ko.observable(undefined), ko.observable(undefined), ko.observable(undefined)]); 
 

 
    self.filterFamily1 = function() { 
 
    return self.family().filter(function(i) { 
 
     return i.parent() == null; 
 
    }); 
 

 
    } 
 
    self.filterFamily2 = ko.computed(function() { 
 
    return ko.utils.arrayFilter(self.family, function(i) { 
 
     return i.parent() === self.array()[0]().name(); 
 
    }); 
 

 
    }); 
 
    self.filterFamily3 = ko.computed(function() { 
 
    return ko.utils.arrayFilter(self.family, function(i) { 
 
     return i.parent() === self.array()[1]().name(); 
 
    }); 
 

 
    }) 
 

 
} 
 

 
var data = { 
 
    family: [{ 
 
    name: "John", 
 
    parent: null 
 
    }, { 
 
    name: "Mary", 
 
    parent: null 
 
    }, { 
 
    name: "Erick", 
 
    parent: "John" 
 
    }, { 
 
    name: "Paul", 
 
    parent: "John" 
 
    }, { 
 
    name: "Marshall", 
 
    parent: "Mary" 
 
    }, { 
 
    name: "Ross", 
 
    parent: "Paul" 
 
    }] 
 
}; 
 

 
var viewModel = new ViewModel(); 
 
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script> 
 

 
<select data-bind="options: $root.filterFamily1(),optionsText: 'name', value: $root.array()[0]"></select> 
 
<select data-bind="options: $root.filterFamily2(),optionsText: 'name', value: $root.array()[1]"></select> 
 
<select data-bind="options: $root.filterFamily3(),optionsText: 'name', value: $root.array()[2]"></select>

但答案是正確的,我之前說明問題。

回答

2

由於您的問題改變了很多,我張貼新的答案:

您的片段有控制檯錯誤:你最初選擇的值未設置也沒有你查詢爲未定義。包括這些檢查,一切正常。

請注意,您絕對可以提高可讀性並重構定期代碼段。

var ViewModel = function() { 
 
    var self = this; 
 
    self.family = ko.mapping.fromJS(data.family); 
 

 

 

 

 
    self.filterFamily1 = ko.computed(function() { 
 
    return self.family().filter(function(i) { 
 
     return i.parent() === null; 
 
    }); 
 

 
    }); 
 

 
    self.array = ko.observableArray([ 
 
    ko.observable(self.filterFamily1()[0]), 
 
    ko.observable(undefined), 
 
    ko.observable(undefined) 
 
    ]); 
 

 
    self.filterFamily2 = ko.computed(function() { 
 
    return self.family().filter(function(i) { 
 
     return self.array()[0]() && i.parent() === self.array()[0]().name(); 
 
    }); 
 

 
    }); 
 
    self.filterFamily3 = ko.computed(function() { 
 
    return self.family().filter(function(i) { 
 
     return self.array()[1]() && i.parent() === self.array()[1]().name(); 
 
    }); 
 

 
    }) 
 

 
} 
 

 
var data = { 
 
    family: [{ 
 
    name: "John", 
 
    parent: null 
 
    }, { 
 
    name: "Mary", 
 
    parent: null 
 
    }, { 
 
    name: "Erick", 
 
    parent: "John" 
 
    }, { 
 
    name: "Paul", 
 
    parent: "John" 
 
    }, { 
 
    name: "Marshall", 
 
    parent: "Mary" 
 
    }, { 
 
    name: "Ross", 
 
    parent: "Paul" 
 
    }] 
 
}; 
 

 
var viewModel = new ViewModel(); 
 
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script> 
 

 
<select data-bind="options: $root.filterFamily1(),optionsText: 'name', value: $root.array()[0]"></select> 
 
<select data-bind="options: $root.filterFamily2(),optionsText: 'name', value: $root.array()[1]"></select> 
 
<select data-bind="options: $root.filterFamily3(),optionsText: 'name', value: $root.array()[2]"></select>

+0

非常感謝,它的工作原理。 – Guto

2

如果你想通過索引訪問數組,你需要首先使用()來評估observable。

如果您希望value綁定雙向工作(即:不僅是初始設置,還會在更改後更新viewmodel中的值),您必須將它們綁定到ko.observable變量。

其他方面的改進:

如果你想加入的所有值加在一起,你可以使用reducemap組合和join追加的字符串。

編輯:我錯了! 如果您需要輸入所有數組的值,則還可以使用綁定並使用$data來引用當前值。

實際上,您無法使用$data關鍵字創建雙向綁定。如果您使用$index觀察值,則可以。

參考:https://github.com/knockout/knockout/issues/708

var ViewModel = function() { 
 
    var self = this; 
 

 
    self.array = ko.observableArray([ko.observable("a"), ko.observable("b"), ko.observable("c")]); 
 

 
    self.text = ko.computed(function() { 
 
    return self.array()[0]() + self.array()[1]() + self.array()[2](); 
 
    }); 
 

 
    self.reducedText = ko.computed(function() { 
 
    return self.array() 
 
     .reduce(function(prev, curr) { 
 
     return prev + curr(); 
 
     }, ""); 
 

 
    }); 
 
}; 
 

 
var viewModel = new ViewModel(); 
 
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<input data-bind="value: array()[0]" /> 
 
<input data-bind="value: array()[1]" /> 
 
<input data-bind="value: array()[2]" /> 
 
<p data-bind="text: text"></p> 
 

 
<!-- EDIT: this does not create a two way binding 
 
<div data-bind="foreach: array"> 
 
    <input data-bind="value: $data" /> 
 
</div> 
 
--> 
 

 
<!-- EDIT: this does work --> 
 
<div data-bind="foreach: array"> 
 
    <input data-bind="value: $parent.array()[$index()]" /> 
 
</div> 
 

 
<p data-bind="text: reducedText"></p>

+0

正如我上面所說,該解決方案工作正常,但我真正的問題是不同的,我認爲,如果它適用於輸入也許適用於選擇了。 – Guto

+0

我已經發布了第二個答案,因爲更新後的包含片段變化很大......您可以在此處找到它:http://stackoverflow.com/a/37416047/3297291 – user3297291

3

Yessir,確實存在。但是:

  1. 項目本身必須是observable s。
  2. 在綁定到其中一個元素之前,您應該執行self.array函數。

下面是一個例子:

var ViewModel = function() { 
 
    var self = this; 
 

 
    self.array = ko.observableArray([ko.observable(""), ko.observable(""), ko.observable("")]); 
 

 
    self.text = ko.computed(function() { 
 
    return self.array()[0]() + self.array()[1]() + self.array()[2](); 
 
    }); 
 
} 
 

 
var viewModel = new ViewModel(); 
 
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<input data-bind="value: $root.array()[0]" /> 
 
<input data-bind="value: $root.array()[1]" /> 
 
<input data-bind="value: $root.array()[2]" /> 
 
<p data-bind="text: $root.text"></p>

但是,爲什麼不使用foreach結合和其它的一些改進?

var ViewModel = function() { 
 
    var self = this; 
 

 
    self.array = ko.observableArray([ 
 
    { txt: ko.observable("a") }, 
 
    { txt: ko.observable("b") }, 
 
    { txt: ko.observable("c") }, 
 
    { txt: ko.observable("d") } 
 
    ]); 
 

 
    self.text = ko.computed(function() { 
 
    return self.array().map(function(obs) { return obs.txt(); }).join(""); 
 
    }); 
 
} 
 

 
var viewModel = new ViewModel(); 
 
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script> 
 

 
<!-- ko foreach: array --> 
 
<input data-bind="textInput: txt"> 
 
<!-- /ko --> 
 
<p data-bind="text: text"></p>

+0

正如我上面所說,解決方案的工作原理很好,但我真正的問題是不同的,我認爲,如果它對輸入起作用也許適用於選擇。 – Guto