Ich versuche eine benutzerdefinierte Bindung in Knockout zu erstellen, die wie der options
Standardbindungshandler funktioniert, aber Radiobuttons anstelle eines Dropdowns verwendet.Knockoutjs Optionsfeldgruppe Benutzerdefinierte Bindung wird bei Auswahl nicht aktualisiert
Das Hinzufügen eines Elements zum Array meldet die update
, aber das Auswählen eines anderen Optionsfelds funktioniert nicht.
Hinweis: Ich habe den Custom-Binding-Handler auf das Nötigste reduziert.
Binding Handler
// LOOK FOR MY COMMENT //<------------------------------ LOOK FOR IT
ko.bindingHandlers.radioButtons = {
update: function (element, valueAccessor, allBindings) {
var unwrappedArray = ko.utils.unwrapObservable(valueAccessor());
var previousSelectedValue = ko.utils.unwrapObservable(allBindings().value);
// Helper function
var applyToObject = function (object, predicate, defaultValue) {
var predicateType = typeof predicate;
if (predicateType == "function") // Given a function; run it against the data value
return predicate(object);
else if (predicateType == "string") // Given a string; treat it as a property name on the data value
return object[predicate];
else // Given no optionsText arg; use the data value itself
return defaultValue;
};
// Map the array to a newly created label and input.
var isFirstPass = true;
var radioButtonForArrayItem = function (arrayEntry, index, oldOptions) {
if (oldOptions.length) {
var item = oldOptions[0];
if ($(item).is(":checked"))
previousSelectedValue = item.value;
isFirstPass = false;
}
var input = element.ownerDocument.createElement("input");
input.type = "radio";
var radioButtonGroupName = allBindings.get("groupName");
input.name = radioButtonGroupName;
if (isFirstPass) {
var selectedValue = ko.utils.unwrapObservable(allBindings.get("value"));
var itemValue = ko.utils.unwrapObservable(arrayEntry.value);
if (selectedValue === itemValue) {
input.checked = true;
}
} else if ($(oldOptions[0].firstElementChild).is(":checked")) {
input.checked = true;
}
var radioButtonValue = applyToObject(arrayEntry, allBindings.get("radioButtonValue"), arrayEntry);
ko.selectExtensions.writeValue(input, ko.utils.unwrapObservable(radioButtonValue));
var label = element.ownerDocument.createElement("label");
label.appendChild(input);
var radioButtonText = applyToObject(arrayEntry, allBindings.get("radioButtonText"), arrayEntry);
label.append(" " + radioButtonText);
return [label];
};
var setSelectionCallback = function (arrayEntry, newOptions) {
var inputElement = newOptions[0].firstElementChild;
if ($(inputElement).is(":checked")) {
var newValue = inputElement.value;
if (previousSelectedValue !== newValue) {
var value = allBindings.get("value");
value(newValue); //<------------------------- Get observable value and set here. Shouldn't this notify the update?
}
}
};
ko.utils.setDomNodeChildrenFromArrayMapping(element, unwrappedArray, radioButtonForArrayItem, {}, setSelectionCallback);
},
};
Wie es zu benutzen ...
// Html
<div data-bind="
radioButtons: letters,
groupName: 'letters',
radioButtonText: 'text',
radioButtonValue: 'value',
value: value,
"></div>
// Javascript
var vm = {
letters: ko.observableArray([
{
text: "A",
value: 1,
},
{
text: "B",
value: 2,
},
]),
value: ko.observable(2),
};
ko.applyBindings(vm);
So, das Hinzufügen eines neuen Elements zur vm.letters({ text: "C", value: 2 })
die update
benachrichtigen. Wenn Sie jedoch auf eine andere Optionsschaltfläche klicken, wird die update
nicht benachrichtigt.
Was muss ich tun, damit das Klicken auf den Radiobutton die update
benachrichtigt?
habe ich einen Hack, aber jetzt fühle ich mich schmutzig ... '$ (Eingang) .auf ("Klick", function() {var value = allBindings.get ("value"); value (this.value);}); ' – christo8989
Ich habe auch bemerkt, dass ich mit' vm.value' keine bidirektionale Bindung bekomme . – christo8989