Frage

Ich habe ein großes ViewModel und möchte die Aktualisierung eines Status ("Lesen"/"ungelesen") auf den Server veröffentlichen, ohne das gesamte Modell zu veröffentlichen.

Was ich getan habe, ist eine benutzerdefinierte Bindung wie SO zu erstellen:

ko.bindingHandlers.statusUpdater = {
    update: function(element, valueAccessor) {
        console.log(element);
    }
};

In der Vorlage:

<div data-bind='template: { name: "contactsListTemplate", data: viewModel.conversations.conversationlist }'> </div>

<script type="text/html" id="contactsListTemplate">
 <table>
  <tbody>
   {{each(i, conversation) $data}}
    <tr>
     <td>
      <input type="checkbox" data-bind="checked: read, statusUpdater: conversation_id" />
     </td>
    </tr>
   {{/each}}
  </tbody>
 </table>
</script>

Für die benutzerdefinierte Bindung interessiere ich mich nur für Updates. Ich dachte, ich würde es mir ermöglichen, ein Update mit KnockoutJs zu erkennen und zu bestimmen, welcher Artikel aktualisiert wurde, damit ich diese Elemente -ID und neue Statistiken erfassen und dann posten kann das zum Server.

Was passiert console.logGing jedes einzelne Kontrollfeld in einer einzigen Kontrollkästchen -Änderung. Dies bedeutet ko.bindingHandlers.statusUpdater.

Ich dachte darüber nach, der Datenbindung ein Klickereignis hinzuzufügen, aber das schien nicht so sauber wie eine benutzerdefinierte Bindung. Vielleicht ist das, was ich mit benutzerdefinierten Bindungen versuche, nicht das, wofür sie sie haben?

Gedanken?

War es hilfreich?

Lösung

Der Grund, warum dies dies tut, liegt daran, dass die Aktualisierungsmethode jeweils als aktualisiert wird und zu Beginn nach der Init -Methode aufgerufen wird.

Die Aktualisierungsbindungsmethode soll den Status des gebundenen DOM -Elements festlegen, wenn sich das ViewModel ändert.

Wenn Sie auf eine Änderung reagieren und das ViewModel aktualisieren möchten, müssen Sie die Init -Methode implementieren und ein Ereignis (klicken, ändern usw.) in diesem Handler anhängen, dann senden Sie das Status -Update an Ihr ViewModel.

ko.bindingHandlers.statusUpdater = {
    'init': function (element, valueAccessor, allBindingsAccessor) {

        var updateHandler = function() {            
            var valueToWrite;
            if (element.type == "checkbox") {
                valueToWrite = element.checked;
            } else if ((element.type == "radio") && (element.checked)) {
                valueToWrite = element.value;
            } else {
                return; // "checked" binding only responds to checkboxes and selected radio buttons
            }

            var modelValue = valueAccessor();

            if (ko.isWriteableObservable(modelValue)) {             
                if (modelValue() !== valueToWrite) { // Suppress repeated events when there's nothing new to notify (some browsers raise them)
                    $.ajax({
                      url: 'someurl',
                      success: function(data) {
                            alert('status update');
                      }
                    });
                    modelValue(valueToWrite);
                }
            } else {
                var allBindings = allBindingsAccessor();
                if (allBindings['_ko_property_writers'] && allBindings['_ko_property_writers']['checked']) {
                    allBindings['_ko_property_writers']['checked'](valueToWrite);
                }
            }
        };

        $(element).click(updateHandler).change(updateHandler);
    },
    'update': function (element, valueAccessor) {
        ko.bindingHandlers.checked(element, valueAccessor);
    }
};

Der beste Weg, dies zu lernen, war, die Debug -Version von Ko auf Git zu betrachten. Was Sie erreichen möchten, ist im Grunde eine modifizierte geprüfte Bindung mit einem Ajax -Aufruf.

Ich habe das oben genannte nicht getestet, aber es sollte Ihnen anfangen.

Prost,

Ian

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top