Knockout Select2 按对象设置初始值
Knockout Select2 set initial value by object
我有一个 Knockout.js 网络应用程序,其中有一个 select2 下拉菜单。我想将 id 和文本值都绑定到一个变量而不仅仅是 id。这是我的数据:
var cars = [{id: 1, name: 'Honda'}, {id: 2, name: 'Toyota'}, {id: 3, name: 'Dodge'}];
var selectedCar = ko.observable();
这是我的 html:
<select data-bind="value: selectedCar, optionsCaption: 'Select', optionsText: 'name', options: cars"></select>
所以现在,每当我 select 下拉列表中的内容时,我的变量包含整个对象,如下所示:
selectedCar = {id: 1, name: 'Honda'};
唯一的问题出现在您加载页面并希望将下拉列表设置为特定值时。即使在呈现 html 之前,selectedCar
变量设置为 {id: 1, name: 'Honda'}
,当页面呈现下拉列表时未设置任何内容,它只是设置为占位符 'Select'。
我做错了什么?
如果要将 id 和文本值都绑定到一个变量,则需要使用 optionsValue
绑定并将整个上下文绑定到它 ($data
);
<select data-bind="value: selectedCar,
optionsCaption: 'Select',
optionsText: 'name',
options: cars,
optionsValue: $data"></select>
通常我们会指定 id 或其他任何内容来选择初始值。因此,在您的问题中,如果湿设置 optionsValue: $data
而不是 $optionsValue: 'id'
,则将整个对象 {id: 1, name: 'Honda'}
作为初始值提供给 selectedCar
是有意义的。
(IMPORTANT) 但事实证明这是行不通的,因为我们正在创建一个新对象,因此当 Knockout 比较 [= 的对象时,它的相等性测试将失败20=] 里面的对象 selectedCar
。设置初始值的正确方法是cars[0]
.
我确定这是一个打字错误,但我还是要说明:当你创建任何需要被 HTML 访问的变量时,你需要将它绑定到 this
,这将是对 viewModel 的引用。
this.cars = [{id: 1, name: 'Honda'}, {id: 2, name: 'Toyota'}, {id: 3, name: 'Dodge'}];
this.selectedCar = ko.observable();
让我们用 fiddle 来测试这一切:
var viewModel = function(){
var self = this;
self.cars = [{id: 1, name: 'Honda'}, {id: 2, name: 'Toyota'}, {id: 3, name: 'Dodge'}];
self.selectedCar = ko.observable(self.cars[0]);
};
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select data-bind="value: selectedCar, optionsCaption: 'Select', optionsText: 'name', optionsValue:$data, options: cars"></select>
<!-- to verify that we are getting the entire object -->
<p data-bind="text: ko.toJSON(selectedCar)"></p>
select框的value
将成为对应select编辑的项目或optionsValue
参数中设置的属性的对象.因此,对于对象,您设置的 selected 值必须与数组中存在的实例相同。拥有一个对象的不同实例恰好在结构上是等价的是不够的。
对于这种情况,我发现将 select 框的值绑定到对象的唯一 ID 更容易。然后你可以通过计算值将该 id 映射到你想要的实际实例。
function ViewModel(data) {
this.cars = data.cars;
this.selectedCarId = ko.observable(data.selectedCarId);
this.selectedCar = ko.computed(() => {
let selectedCarId = this.selectedCarId();
return this.cars.find(c => c.id === selectedCarId);
});
}
let model = {
cars: [
{ id: 1, name: 'Honda' },
{ id: 2, name: 'Toyota' },
{ id: 3, name: 'Dodge' }
],
selectedCarId: 2
};
ko.applyBindings(new ViewModel(model), document.getElementById('content'));
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/js/select2.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.min.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div id="content">
<select data-bind="value: selectedCarId,
optionsCaption: 'Select',
optionsText: 'name',
optionsValue: 'id',
options: cars">
</select>
<p>selectedCarId: <span data-bind="text: selectedCarId"></span></p>
<p>selectedCar: <span data-bind="text: ko.toJSON(selectedCar)"></span></p>
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
</div>
如果您不想使用单独的计算 属性,您仍然需要传入一个索引,但您设置的值必须从数组中获取。
function ViewModel(data) {
this.cars = data.cars;
this.selectedCar = ko.observable(
data.cars.find(c => c.id === data.selectedCarId)
);
}
我有一个 Knockout.js 网络应用程序,其中有一个 select2 下拉菜单。我想将 id 和文本值都绑定到一个变量而不仅仅是 id。这是我的数据:
var cars = [{id: 1, name: 'Honda'}, {id: 2, name: 'Toyota'}, {id: 3, name: 'Dodge'}];
var selectedCar = ko.observable();
这是我的 html:
<select data-bind="value: selectedCar, optionsCaption: 'Select', optionsText: 'name', options: cars"></select>
所以现在,每当我 select 下拉列表中的内容时,我的变量包含整个对象,如下所示:
selectedCar = {id: 1, name: 'Honda'};
唯一的问题出现在您加载页面并希望将下拉列表设置为特定值时。即使在呈现 html 之前,selectedCar
变量设置为 {id: 1, name: 'Honda'}
,当页面呈现下拉列表时未设置任何内容,它只是设置为占位符 'Select'。
我做错了什么?
如果要将 id 和文本值都绑定到一个变量,则需要使用 optionsValue
绑定并将整个上下文绑定到它 ($data
);
<select data-bind="value: selectedCar,
optionsCaption: 'Select',
optionsText: 'name',
options: cars,
optionsValue: $data"></select>
通常我们会指定 id 或其他任何内容来选择初始值。因此,在您的问题中,如果湿设置 optionsValue: $data
而不是 $optionsValue: 'id'
,则将整个对象 {id: 1, name: 'Honda'}
作为初始值提供给 selectedCar
是有意义的。
(IMPORTANT) 但事实证明这是行不通的,因为我们正在创建一个新对象,因此当 Knockout 比较 [= 的对象时,它的相等性测试将失败20=] 里面的对象 selectedCar
。设置初始值的正确方法是cars[0]
.
我确定这是一个打字错误,但我还是要说明:当你创建任何需要被 HTML 访问的变量时,你需要将它绑定到 this
,这将是对 viewModel 的引用。
this.cars = [{id: 1, name: 'Honda'}, {id: 2, name: 'Toyota'}, {id: 3, name: 'Dodge'}];
this.selectedCar = ko.observable();
让我们用 fiddle 来测试这一切:
var viewModel = function(){
var self = this;
self.cars = [{id: 1, name: 'Honda'}, {id: 2, name: 'Toyota'}, {id: 3, name: 'Dodge'}];
self.selectedCar = ko.observable(self.cars[0]);
};
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select data-bind="value: selectedCar, optionsCaption: 'Select', optionsText: 'name', optionsValue:$data, options: cars"></select>
<!-- to verify that we are getting the entire object -->
<p data-bind="text: ko.toJSON(selectedCar)"></p>
select框的value
将成为对应select编辑的项目或optionsValue
参数中设置的属性的对象.因此,对于对象,您设置的 selected 值必须与数组中存在的实例相同。拥有一个对象的不同实例恰好在结构上是等价的是不够的。
对于这种情况,我发现将 select 框的值绑定到对象的唯一 ID 更容易。然后你可以通过计算值将该 id 映射到你想要的实际实例。
function ViewModel(data) {
this.cars = data.cars;
this.selectedCarId = ko.observable(data.selectedCarId);
this.selectedCar = ko.computed(() => {
let selectedCarId = this.selectedCarId();
return this.cars.find(c => c.id === selectedCarId);
});
}
let model = {
cars: [
{ id: 1, name: 'Honda' },
{ id: 2, name: 'Toyota' },
{ id: 3, name: 'Dodge' }
],
selectedCarId: 2
};
ko.applyBindings(new ViewModel(model), document.getElementById('content'));
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/js/select2.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.min.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div id="content">
<select data-bind="value: selectedCarId,
optionsCaption: 'Select',
optionsText: 'name',
optionsValue: 'id',
options: cars">
</select>
<p>selectedCarId: <span data-bind="text: selectedCarId"></span></p>
<p>selectedCar: <span data-bind="text: ko.toJSON(selectedCar)"></span></p>
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
</div>
如果您不想使用单独的计算 属性,您仍然需要传入一个索引,但您设置的值必须从数组中获取。
function ViewModel(data) {
this.cars = data.cars;
this.selectedCar = ko.observable(
data.cars.find(c => c.id === data.selectedCarId)
);
}