在 Knockoutjs 绑定中有什么方法可以指定 optionsGroup 吗?类似以下的东西
<select data-bind="options: collection, optionsText: 'Text', optionsGroup: 'Group'/>
请回复。
在 Knockoutjs 绑定中有什么方法可以指定 optionsGroup 吗?类似以下的东西
<select data-bind="options: collection, optionsText: 'Text', optionsGroup: 'Group'/>
请回复。
我得到了相同的答案,如果有人想要,这里是答案,
<td><select class="fieldValue" data-bind="foreach: $root.AvailableFields, value: FieldId, event :{ change: $root.onFieldSelectionChange}">
<optgroup data-bind="attr: {label: FieldGroupName}, foreach: Fields">
<option data-bind="text: HeaderText, value: FieldId"></option>
</optgroup>
</select>
</td>
在许多情况下,您不需要选项本身是可观察的,只需要选择的结果即可。这是进行英国县选择的示例。
HTML:
<div class="form-group">
<label for="county">County</label>
<select class="fieldValue" data-bind="foreach: $root.countyList, value: orgCounty">
<optgroup data-bind="attr: {label: label}, foreach: counties">
<option data-bind="text: label, value: label"></option>
</optgroup>
</select>
</div>
JS:
viewModel.countyList = getCountyList();
viewModel.orgCounty = ko.observable('London'); // Put default value here
function getCountyList() {
var $arrayCounties = [
{ "label" : "England", "counties" : [
{ "label" : "Bedfordshire"},
{ "label" : "Berkshire"},
{ "label" : "Bristol"},
{ "label" : "Buckinghamshire"},
{ "label" : "Cambridgeshire"},
{ "label" : "Cheshire"},
{ "label" : "City of London"},
{ "label" : "Cornwall"},
{ "label" : "Cumbria"},
{ "label" : "Derbyshire"},
{ "label" : "Devon"},
{ "label" : "Dorset"},
{ "label" : "Durham"},
{ "label" : "East Riding of Yorkshire"},
{ "label" : "East Sussex"},
{ "label" : "Essex"},
{ "label" : "Gloucestershire"},
{ "label" : "Greater London"},
{ "label" : "Greater Manchester"},
{ "label" : "Hampshire"},
{ "label" : "Herefordshire"},
{ "label" : "Hertfordshire"},
{ "label" : "Isle of Wight"},
{ "label" : "Kent"},
{ "label" : "Lancashire"},
{ "label" : "Leicestershire"},
{ "label" : "Lincolnshire"},
{ "label" : "Merseyside"},
{ "label" : "Norfolk"},
{ "label" : "North Yorkshire"},
{ "label" : "Northamptonshire"},
{ "label" : "Northumberland"},
{ "label" : "Nottinghamshire"},
{ "label" : "Oxfordshire"},
{ "label" : "Rutland"},
{ "label" : "Shropshire"},
{ "label" : "Somerset"},
{ "label" : "South Yorkshire"},
{ "label" : "Staffordshire"},
{ "label" : "Suffolk"},
{ "label" : "Surrey"},
{ "label" : "Tyne and Wear"},
{ "label" : "Warwickshire"},
{ "label" : "West Midlands"},
{ "label" : "West Sussex"},
{ "label" : "West Yorkshire"},
{ "label" : "Wiltshire"},
{ "label" : "Worcestershire"} ]},
{ "label" : "Wales", "counties" : [
{ "label" : "Anglesey"},
{ "label" : "Brecknockshire"},
{ "label" : "Caernarfonshire"},
{ "label" : "Carmarthenshire"},
{ "label" : "Cardiganshire"},
{ "label" : "Denbighshire"},
{ "label" : "Flintshire"},
{ "label" : "Glamorgan"},
{ "label" : "Merioneth"},
{ "label" : "Monmouthshire"},
{ "label" : "Montgomeryshire"},
{ "label" : "Pembrokeshire"},
{ "label" : "Radnorshire"} ]},
{ "label" : "Scotland", "counties" : [
{ "label" : "Aberdeenshire"},
{ "label" : "Angus"},
{ "label" : "Argyllshire"},
{ "label" : "Ayrshire"},
{ "label" : "Banffshire"},
{ "label" : "Berwickshire"},
{ "label" : "Buteshire"},
{ "label" : "Cromartyshire"},
{ "label" : "Caithness"},
{ "label" : "Clackmannanshire"},
{ "label" : "Dumfriesshire"},
{ "label" : "Dunbartonshire"},
{ "label" : "East Lothian"},
{ "label" : "Fife"},
{ "label" : "Inverness-shire"},
{ "label" : "Kincardineshire"},
{ "label" : "Kinross"},
{ "label" : "Kirkcudbrightshire"},
{ "label" : "Lanarkshire"},
{ "label" : "Midlothian"},
{ "label" : "Morayshire"},
{ "label" : "Nairnshire"},
{ "label" : "Orkney"},
{ "label" : "Peeblesshire"},
{ "label" : "Perthshire"},
{ "label" : "Renfrewshire"},
{ "label" : "Ross-shire"},
{ "label" : "Roxburghshire"},
{ "label" : "Selkirkshire"},
{ "label" : "Shetland"},
{ "label" : "Stirlingshire"},
{ "label" : "Sutherland"},
{ "label" : "West Lothian"},
{ "label" : "Wigtownshire"} ]},
{ "label" : "Northern Ireland", "counties" : [
{ "label" : "Antrim"},
{ "label" : "Armagh"},
{ "label" : "Down"},
{ "label" : "Fermanagh"},
{ "label" : "Londonderry"},
{ "label" : "Tyrone"} ]}
];
return $arrayCounties;
}
您将在 viewModel.countyList 中检索选定的选项。
这也将允许占位符:
<select class="form-control needsclick" data-bind="value: Value">
<option value="" disabled selected>Select Value...</option>
<!-- ko foreach: Group -->
<optgroup data-bind="attr: { label: Label }, foreach: Collection">
<option data-bind="text: Label, value: $data"></option>
</optgroup>
<!-- /ko -->
</select>
JS 将采用这种格式:
self.Group = ko.pauseableComputed(function () {
var groups = [
{
Label: 'Group 1',
Collection: [
{ Label: 'Data 1', Value: 'Data 1' },
{ Label: 'Data 2', Value: 'Data 2' },
]
},
{
Label: 'Group 2',
Collection: [
{ Label: 'Data 3', Value: 'Data 3' },
{ Label: 'Data 4', Value: 'Data 4' },
]
},
]
return groups;
})
这个选项值,可以是这个简单实例中的值。
<option data-bind="text: Label, value: Value"></option>
但对于更复杂的对象 $data 将是更好的选择。
试试这个。
(function () {
ko.bindingHandlers["groupedOptions"] = {
update: function (element, valueAccessor, allBindingsAccessor) {
if (element.tagName != "SELECT")
throw new Error("groupedOptions binding applies only to SELECT elements");
var previousSelectedValues = [];
for (var i = 0; i < element.childNodes.length; i++) {
var node = element.childNodes[i];
if (node.tagName == "OPTGROUP") {
if (node.childNodes != undefined) {
for (var k = 0; k < node.childNodes.length; k++) {
var childNode = node.childNodes[k];
if (childNode.tagName && childNode.tagName && childNode.tagName == "OPTION" && childNode.selected) {
previousSelectedValues.push(ko.selectExtensions.readValue(childNode));
}
}
}
} else if (node.tagName && node.tagName == "OPTION" && node.selected) {
previousSelectedValues.push(ko.selectExtensions.readValue(node));
}
}
var previousScrollTop = element.scrollTop;
var value = ko.utils.unwrapObservable(valueAccessor());
// Clear existing elements
element.innerHTML = "";
if (value) {
var allBindings = allBindingsAccessor();
if (typeof value.length != "number")
value = [value];
if (allBindings['optionsCaption']) {
var option = document.createElement("OPTION");
option.innerHTML = allBindings['optionsCaption'];
ko.selectExtensions.writeValue(option, undefined);
element.appendChild(option);
}
var optionsGroupNamesValue = allBindings['optionsGroupNames'];
// Group values into optgroups
var groupedOptions = [];
var optionsGroupValue = allBindings['optionsGroup']; // undefined if not given
for (var i = 0, j = value.length; i < j; i++) {
var optionsGroup = null;
if (typeof optionsGroupValue == "function")
optionsGroup = optionsGroupValue(value[i]);
else if (typeof optionsGroupValue == "string")
optionsGroup = value[i][optionsGroupValue];
else
optionsGroup = "";
if (typeof groupedOptions[optionsGroup] == "undefined")
groupedOptions[optionsGroup] = [];
groupedOptions[optionsGroup].push(value[i]);
}
// Create HTML elements
for (var groupName in groupedOptions) {
var optgroup = null;
// Add an OPTGROUP for all groups except for ""
if (groupName != "") {
optgroup = document.createElement("OPTGROUP");
optgroup.label = groupName;
element.appendChild(optgroup);
}
// Create HTML elements for options within this group
for (var i = 0, j = groupedOptions[groupName].length; i < j; i++) {
var valueGroup = groupedOptions[groupName];
var option = document.createElement("OPTION");
var optionValue = typeof allBindings['optionsValue'] == "string" ? valueGroup[i][allBindings['optionsValue']] : valueGroup[groupName][i];
// Pick some text to appear in the drop-down list for this data value
var optionsTextValue = allBindings['optionsText'];
if (typeof optionsTextValue == "function")
optionText = optionsTextValue(valueGroup[i]); // Given a function; run it against the data value
else if (typeof optionsTextValue == "string")
optionText = valueGroup[i][optionsTextValue]; // Given a string; treat it as a property name on the data value
else
optionText = optionValue; // Given no optionsText arg; use the data value itself
optionValue = ko.utils.unwrapObservable(optionValue);
optionText = ko.utils.unwrapObservable(optionText);
ko.selectExtensions.writeValue(option, optionValue);
option.innerHTML = optionText.toString();
if (optgroup != null)
optgroup.appendChild(option);
else
element.appendChild(option);
}
}
// IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
// That's why we first added them without selection. Now it's time to set the selection.
var newOptions = element.getElementsByTagName("OPTION");
var countSelectionsRetained = 0;
for (var i = 0, j = newOptions.length; i < j; i++) {
if (ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[i])) >= 0) {
ko.utils.setOptionNodeSelectionState(newOptions[i], true);
countSelectionsRetained++;
}
}
if (previousScrollTop)
element.scrollTop = previousScrollTop;
}
}
};
ko.bindingHandlers['selectedOptions'] = {
getSelectedValuesFromSelectNode: function (selectNode) {
var result = [];
var nodes = selectNode.childNodes;
for (var i = 0, j = nodes.length; i < j; i++) {
var node = nodes[i];
if ((node.tagName == "OPTGROUP") && node.childNodes != null) {
var subResult = this.getSelectedValuesFromSelectNode(node);
for (var k = 0; k < subResult.length; k++) {
result.push(subResult[k]);
}
}
else {
if ((node.tagName == "OPTION") && node.selected)
result.push(ko.selectExtensions.readValue(node));
}
}
return result;
},
setSelectedValuesFromSelectNode: function (selectNode, newValue) {
var nodes = selectNode.childNodes;
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
if (node.tagName == "OPTION") {
ko.utils.setOptionNodeSelectionState(node, ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0);
}
else if (node.tagName == "OPTGROUP") {
for (var k = 0; k < node.childNodes.length; k++) {
var childNode = node.childNodes[k];
if (childNode.tagName && childNode.tagName == "OPTION") {
ko.utils.setOptionNodeSelectionState(childNode, ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(childNode)) >= 0);
}
}
}
}
},
'init': function (element, valueAccessor, allBindingsAccessor) {
ko.utils.registerEventHandler(element, "change", function () {
var value = valueAccessor();
if (ko.isWriteableObservable(value))
value(ko.bindingHandlers['selectedOptions'].getSelectedValuesFromSelectNode(this));
else {
var allBindings = allBindingsAccessor();
if (allBindings['_ko_property_writers'] && allBindings['_ko_property_writers']['value'])
allBindings['_ko_property_writers']['value'](ko.bindingHandlers['selectedOptions'].getSelectedValuesFromSelectNode(this));
}
});
},
'update': function (element, valueAccessor) {
if (element.tagName != "SELECT")
throw new Error("values binding applies only to SELECT elements");
var newValue = ko.utils.unwrapObservable(valueAccessor());
if (newValue && typeof newValue.length == "number") {
ko.bindingHandlers['selectedOptions'].setSelectedValuesFromSelectNode(element, newValue);
}
}
};
})();
<select data-bind="groupedOptions: collection, optionsText: 'Text', optionsValue: 'Value', optionsGroup: 'Group', selectedOptions: Selected"></select>