update knockout for data change knockout.js knockout-mapping-plugin

knockout.js - for - Knockoutjs seleccionar con el grupo de opciones



ko js value update (4)

En muchos casos, no es necesario que las opciones sean observables, solo el resultado de la selección. Aquí está el ejemplo que hace la selección del condado del Reino Unido.

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

Recuperarás la opción seleccionada en viewModel.countyList.

¿Hay alguna forma en el enlace de Knockoutjs donde pueda especificar optionsGroup? algo como seguir

<select data-bind="options: collection, optionsText: ''Text'', optionsGroup: ''Group''/>

Por favor, responda.


Esto también permitirá un marcador de posición:

<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 estaría en este formato:

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

Este valor de opción, podría ser valor en esta simple instancia.

<option data-bind="text: Label, value: Value"></option>

Pero para objetos más complejos, $ data sería la mejor opción.


Prueba esto.

(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>

jsfiddle

source


Tengo la respuesta de la misma, aquí está la respuesta si alguien quiere,

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