2012-04-01 14 views
12

Ich versuche, ein Raster zu etablieren und es mit mehr Datensätzen über JSON zu aktualisieren. In diesem einfachen Beispiel kann ich die erforderliche Funktionalität erreichen, aber ich kann nur einen JSON-Datensatz aktualisieren/schieben. Ich würde gerne mehrere Datensätze über JSON hinzufügen können? Wie könnte ich das erreichen? Ich nahm an, dass ich vielleicht eine Art for-Schleife erstellen müsste und jedes JSON-Ergebnis auf die Observable schieben müsste, aber ich hatte gehofft, dass Knockout eine bessere Möglichkeit zum Aktualisieren/Parsen über JSON haben könnte?Update Knockout.js Observable von JSON

Heres eine Kopie von dem, was ich bisher erreicht habe: http://jsfiddle.net/sparkhill/crSbt/

 function Users(user_id, password) { 
    this.user_id = ko.observable(); 
    this.password = ko.observable(); 
} 

var viewModel = { 

    users: ko.observableArray([]), 


    addUser: function() { 
     this.users.push({ 

      user_id: "", 
      password: "" 
     }); 
    }, 

    addJSON: function() { 


     //Works Fine 
     var JSONdataFromServer 
     ='{"user_id":"frances","password":"password"}'; 

     //More than one result - wont map - Would Ideally like to map lots of records at one time 
//var JSONdataFromServer ='{"user_id":"frances","password":"password"}, {"user_id":"frances","password":"password"}'; 

     var dataFromServer = ko.utils.parseJson(JSONdataFromServer); 


     this.users.push(dataFromServer); 

     //Tried 
     //this.users.push(JSON.parse(JSONdataFromServer)); 


    } 

}; 

viewModel.users(); 
ko.applyBindings(viewModel); 

    </script> 

aktualisiert dies scheint zu funktionieren, aber ich frage mich, ob sie eine effizientere Methode ist?

addJSON: function() { 

     //Works Fine 
     var JSONdataFromServer 
     ='[{"user_id":"frances","password":"password"},{"user_id":"timmy","password":"password"}]'; 

     var results = JSON.parse(JSONdataFromServer); 

     var i = results.length; 

     for(var i = 0; i < results.length; i++){ 

      this.users.push(results[i]); 
     }; 

Antwort

22

Hier sind 3 Möglichkeiten, wie Sie dies tun könnte ... in dieser Geige gefunden: http://jsfiddle.net/johnpapa/nfnbD/

1) Verwenden Sie die ko .utils.arrayPushAll Funktion 2) verwenden Sie Ihre eigene Logik 3) Schreiben Sie Ihre eigene Funktion auf observableArray

Details ...

1) Wenn Sie die ko.utils.arrayPushAll Funktion verwenden, müssen Sie valueHasMutated nennen, da das Array effektiv mit sich selbst überschrieben wird. Die Beobachtbarkeit feuert nicht ab, du sagst es, dass es sich verändert hat. Hier ist, wie Sie könnten das tun:

ko.utils.arrayPushAll(this.users(), dataFromServer); 
this.users.valueHasMutated(); 

2) Die zweite Option ist für Ihre eigene Schleife Logik zu schreiben, im wesentlichen den gleichen Code wie der arrayPushAll Funktion wie folgt verwendet.

for (var i = 0, j = dataFromServer.length; i < j; i++) 
this.users.push(dataFromServer[i]); 

3) Erstellen Sie eine Funktion der eigenen auf dem observableArray, wie folgt aus:

ko.observableArray.fn.pushAll = function(valuesToPush) { 
     var items = this; 
     for (var i = 0, j = valuesToPush.length; i < j; i++){ 
      items.push(valuesToPush[i]); 
     } 
     return items; 
}; 

Obwohl dieser Code über jedes Mal ein Element hinzugefügt wird benachrichtigt. Es könnte also besser sein, sie alle hinzuzufügen und dann zu benachrichtigen. Dies wäre effizienter. Wie folgt aus:

ko.observableArray.fn.pushAll = function(valuesToPush) { 
    var underlyingArray = this(); 
    this.valueWillMutate(); 
    ko.utils.arrayPushAll(underlyingArray, valuesToPush); 
    this.valueHasMutated(); 
    return this; 
}; 

Dann rufen Sie es wie folgt aus:

this.users.pushAll(dataFromServer); 
+0

Denken Sie daran, dass Sie möglicherweise eine Instanzvariable Ihres Modells erstellen müssen, wenn Sie Ihr ObservableArray von irgendwo auf Ihrer Seite außerhalb des eigentlichen Modells aktualisieren möchten, zB: 'var myModelInstance = new Viewmodel();' ' ko.utils.arrayPushAll (myModelInstance.users(), dataFromServer);' ' myModelInstance.users.pushall –

+1

Ist das noch die Art und Weise mit der Version 3.1 zu gehen? – Homer

+0

Ich stelle die gleiche Frage wie Homer. Ist 'pushAll' bereits im Kern von KnockoutJs seit Version 3.1. – Samuel

3

Sie können das mapping Plugin

Siehe http://knockoutjs.com/documentation/plugins-mapping.html

+0

wie funktioniert Mapping-Plugin Hilfe mit dem Problem? –

+0

Siehe Abschnitt "Erweiterte Verwendung" (im verlinkten Artikel verfügbar). Mit dem Plugin können Sie den Prozess der Aktualisierung/Erstellung anpassen –

1

Ich weiß, das ist eine ganz alte Post, aber ich kam über sie und dachte nur, ich einen anderen Weg zeigen würde, dies zu tun in Knockout ohne eigene pushAll für zukünftige Besucher zu erstellen.

Sie können ein push.apply in Knockout auf einem beobachtbaren Array verwenden. Dadurch können Sie mehrere Elemente von einem Server übertragen und nur eine Benachrichtigung auslösen.

Example in JsFiddle

bearbeiten: Die further reading für jedermann Lesen Sie dieses, warum wissen will push.apply verwenden, anstatt der Verwendung von push in einer Schleife