2013-12-16 6 views
5

Ich versuche, die in knockout Version 3 eingeführte checkedValue-Bindung mit Optionsfeldern zu verwenden, bekomme aber nicht das von mir erwartete Verhalten.Verwendung der checkedValue-Bindung mit Optionsfeldern

Hier ist ein Beispiel: (die Ansichtsmodell zwei Eigenschaften hat; list ist ein Array; checkedVal ist eine beobachtbare)

<div data-bind="foreach:list"> 
    <input type="radio" data-bind=" 
     checkedValue: { 
      data: $data, 
      index: $index(), 
     }, 
     checked: $parent.checkedVal 
    "/> 
    <span data-bind="text: $data"></span> 
</div> 

JSFiddle

ich die Radio-Buttons erwarten normal zu verhalten, und checkedVal zu sein ein Objekt, das die Daten und den Index enthält. checkedVal ist wie ich es erwarte, aber die Optionsfelder wählen nicht aus. Seltsamerweise ist das Verhalten in meinem tatsächlichen Code inkonsistent; manchmal funktionieren die Radio-Knöpfe und manchmal nicht, aber es funktioniert in der Geige nicht, soweit ich das beurteilen kann.

Ist das ein Fehler, oder verstehe ich nicht, wie das funktionieren soll?

Antwort

0

Es scheint, dass dieses Problem in neueren Versionen von KO gelöst. Ab Version 3.2 sehe ich dieses Verhalten nicht mehr in meiner ursprünglichen Frage.

Hier ist ein working JSFiddle, identisch mit dem Original, außer mit KO auf 3.2 aktualisiert.

1

Ihre checkedValue Bindung wird eine Funktion wie folgt:

function() { 
    return { 
     data: $data, 
     index: $index(), 
    }; 
} 

Jedes Mal, die checked Binding Updates, es ruft diese Funktion auf den Wert zu erhalten. Aber die Funktion gibt immer ein neues Objekt zurück. Obwohl die Objekte dieselben Daten enthalten, werden sie von Knockout nicht als identisch angesehen.

Sie können dies lösen, indem Sie den Wert eine Zeichenfolge machen.

<input type="radio" data-bind=" 
     checkedValue: JSON.stringify({ 
      data: $data, 
      index: $index(), 
     }), 
     checked: $parent.checkedVal 
    "/> 

Oder durch Bindung an einen konsistenten Wert.

<input type="radio" data-bind=" 
     checkedValue: $data, 
     checked: $parent.checkedVal 
    "/> 

EDIT:

Sie eine benutzerdefinierte Bindung verwenden können, die das gleiche Muster wie checked folgt, sondern ermöglicht eine Vergleichsfunktion.

ko.bindingHandlers.radioChecked = { 
    init: function (element, valueAccessor, allBindings) { 
     ko.utils.registerEventHandler(element, "click", function() { 
      if (element.checked) { 
       var observable = valueAccessor(), 
        checkedValue = allBindings.get('checkedValue'); 
       observable(checkedValue); 
      } 
     }); 
    }, 
    update: function (element, valueAccessor, allBindings) { 
     var modelValue = valueAccessor()(), 
      checkedValue = allBindings.get('checkedValue'), 
      comparer = allBindings.get('checkedComparer'); 
     element.checked = comparer(modelValue, checkedValue); 
    } 
}; 

Dann können Objekte nach Inhalt verglichen werden.

this.itemCompare = function(a, b) { 
    return JSON.stringify(a) == JSON.stringify(b); 
} 

jsFiddle: http://jsfiddle.net/mbest/Q4LSQ/

+0

Wenn das stimmt, dann sehe ich den Punkt von checkedValue nicht; das erste Beispiel hätte sicherlich nur mit "Wert" gearbeitet, und ich denke, das zweite wäre es auch. – Retsam

+0

Sie könnten an der benutzerdefinierten Bindung interessiert sein, die ich hinzugefügt habe und die anstelle von "checked" verwendet werden kann und eine Vergleichsfunktion unterstützt. –

Verwandte Themen