2016-06-01 6 views
-1

Alle,Wie auf einem Wert, der eine Abhängigkeit zu Setup von einem Server in Knockout kommenden

HINWEIS (mein Setup):

Knockout JS lib

Knockout-Mapping lib (mein Ansicht-Modell Verwendung von Knockout-Mapping js lib)

ich habe ein Benutzer eine Rechnung Form und jedes Mal ändert, wird auf dem Server erzeugt und zu beobachtbaren VM umgewandelt einer der folgenden Werte:

Menge, Einzelpreis

Ich möchte auf den Server gehen, um die Gesamtsteuer zu berechnen und diese Steuer in einer Spanne zu rendern.

Ich bin auf der Suche nach Code in Knockout, die den berechneten Gesamtsteuerwert vom Server zurückgegeben asynchron zurückgibt und es enthält Abhängigkeit Kette auf Menge und Stückpreis. Die Schwierigkeit hierbei besteht darin, dass die Serveraufrufe asynchron sind und wie ich eine Aktualisierung in Knockout auslösen kann.

UPDATE:

ich unten an der Lösung zurückgegriffen, schlagen Sie bitte, ob es eine bessere Antwort. Nur zu dieser Lösung Nachteil ist, wenn das Formular für alle Steuerelemente, die onchange-Ereignis ausgelöst wird Databound ist, der dieses Ereignis haben Bindung (so dass einmal ist pro Position):

<input data-bind="value: Quantity, event:{ change: calculateTax()}" /> 

<td data-bind="text: renderCurrency(tax())"></td> 


vm.tax = ko.observable(0); 

function calculateTax() { 
    var document = ko.mapping.toJS(vm).Document; 
    var json = JSON.stringify(document); 
    svc.GetTax(json, 
     function(results, ctx, methodName) { 
      var mny = results; 
      vm.tax(mny.Amount); 
     } 
    ); 
} 
+0

Es nützlich sein würde, wenn Sie den zweiten Teil erwägen, entweder ein integraler Bestandteil des Posts oder einen separate Antwort. Stellen Sie außerdem sicher, dass Ihre Frage ein [mcve] enthält (ich habe Ihren Kommentar zu der Antwort gesehen, der auf die Tatsache hinweist, dass Sie ko.mapping haben, diese Dinge sind wichtig, wenn wir bei der Suche nach einer Lösung helfen). – Jeroen

+0

Mein schlechtes, ich habe meine Frage bearbeitet. – ActiveX

Antwort

0

in dieser Art von Fällen habe ich verwendet, was ich ein asyncComputed nenne. Dadurch kann der Steuerwert von einer oder mehreren Observablen (Menge, Stückpreis) abhängen und aktualisiert werden, sobald ein Ergebnis vom Server zurückgegeben wird. Hier ist eine mögliche Implementierung:

ko.asyncComputed = function (fn, defaultValue) { 
    var value = ko.observable defaultValue 

    var result = ko.computed(() => value()) 

    result.loading = ko.observable(true) 

    ko.computed(function() { 
    result.loading(true) 

    Promise.resolve(fn()).then(function (asyncResult) { 
     result.loading(false) 
     value(asyncResult) 
    } 
    } 

    return result 
} 

Beachten Sie, dass die fn Parameter erwartet wird, eine Funktion zu sein, ein Versprechen der Rückkehr, das ist, was zum Beispiel jQuery Ajax bereits der Fall ist.

die svc.GetTax Unter der Annahme gibt ein Versprechen, das ist, wie es in Ihrem Fall zutreffen:

vm.tax = ko.asyncComputed(function() { 
    var document = ko.mapping.toJS(vm).Document; 
    var json = JSON.stringify(document); 
    return svc.GetTax(json).then((results) => results.Amount); 
} 
+0

Die Schlüsselwörter then() und Lambda-Ausdruck sind diese gültigen EcmaScript? Oder sind sie Teil einer Bibliothek? Können Sie erklären? – ActiveX

+0

Die Pfeilfunktion und Promise (und dann eine Funktion in der Promise-Instanz) sind Teil von Ecmascript 6. Sie werden heute recht gut unterstützt.Wenn Sie alte Browser unterstützen müssen, können Sie das Versprechen-Muster durch einen Rückruf und den Fettpfeil mit einfacher alter Funktionsdefinition ersetzen. – DonSteep

+0

Danke Don. 1 weitere Frage zur Lösung: Es scheint, dass die Async-Berechnung ausgeführt wird, wenn sich Eigenschaften im Dokument ändern. Ich möchte nur eine asynchrone Anfrage, wenn sich die Menge oder der Einheitspreis ändert. Sehen Sie, mein asynchronen Vertrag nimmt ein Dokument, aber ich möchte es nur ausführen, wenn Menge, Stückpreis ändern. Wie stelle ich fest, dass Knockout nur auf diesen 2 Eigenschaften berechnet werden soll? – ActiveX

0

Sie die subscribe im observable verwenden können, ist ein PubSub Muster im KO umgesetzt, more info Siehe das Beispiel:

function ViewModel(){ 
 
    this.Quantity =ko.observable(); 
 
    this.tax = ko.observable(); 
 
    
 
    this.Quantity.subscribe(function(){ 
 
     this.calculeTax(); 
 
    },this); 
 
}; 
 

 
ViewModel.prototype.calculeTax = function(){ 
 
    //Here you will do the ajax call 
 
    this.tax(this.Quantity()*10); 
 
}; 
 

 
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 

 
<input data-bind="value: Quantity" /> 
 
<br/> 
 

 
<span>If you want to update on keydown use the textInput bind handler:<span> 
 
    <br/> 
 
<input data-bind="textInput: Quantity" /> 
 
<br/> 
 
<br/> 
 

 
<span data-bind="text: tax"></span>

+0

Danke für Ihre Antwort. Eine Sache: 1) Ich habe keinen Zugriff auf mein ViewModel deklarativ, es wird mit ko.mapping.fromJS() vom Server generiert. Dies erschwert das Hinzufügen Ihres Vorschlags. – ActiveX

Verwandte Themen