2012-04-18 2 views
6

Gerade jetzt, ich bin mit dieser JSON mit der Plugin KO Mapping und es funktioniert gut:Performing partielles Updates mit KnockoutJS Mapping-Plugin

{ 
    "Controls": [ 
    { 
     "Fields": [ 
     { 
      "Name": "emailField", 
      "Text": "email", 
      "Visible": true 
     }, 
     { 
      "Name": "hiddenField", 
      "Text": "text", 
      "Visible": true 
     } 
     ], 
     "Name": "form2", 
     "Type": "Form" 
    }, 
    { 
     "Data": [ 
     [ 
      "Federico Aloi", 
      20 
     ], 
     [ 
      "Andres Lopez", 
      31 
     ], 
     [ 
      "Pablo Perez", 
      32 
     ] 
     ], 
     "Fields": [ 
     { 
      "Name": "nameField", 
      "Text": "Nombre", 
      "Visible": true 
     }, 
     { 
      "Name": "ageField", 
      "Text": "Edad", 
      "Visible": true 
     } 
     ], 
     "Name": "datagrid1", 
     "Type": "Datagrid" 
    } 
    ], 
    "Name": "pagina1", 
    "Title": "Probando el KO" 
} 

Jetzt ist meine Anforderung "partielles Updates" durchzuführen. Einige Szenarien, wenn ich das tun möchte:

  • Ich muss das Data-Array in der zweiten Kontrolle ändern.
  • Ich muss nur ein Steuerelement und nicht die ganze Seite aktualisieren (das ist die Klasse, die ich serialisieren, die Wurzel in diesem JSON).
  • Ich muss ein anderes Steuerelement zu meiner Seite hinzufügen.

Vielleicht wäre eine andere Problemumgehung das ursprüngliche Objekt neu zu erstellen, es mit ko.mapping.toJS(viewModel), ändern und dann wieder re-map ... aber ich glaube, dass Sie besser mit etwas herauskommen wird.


EDIT: Ich habe versucht, mit ko.mapping.fromJS(updatedControl, viewModel.Controls()[0]) aber es hat nicht funktioniert, hier ist mein Code:

function (control) { 
    $.getJSON($.format('api/control/{0}/{1}', viewModel.Name(), control.Name()), function (response) { 
     ko.mapping.fromJS(response, viewModel.Controls()[0]); 
    }); 
}, 

Antwort:

{ 
    "Fields": [ 
    { 
     "Name": "emailField", 
     "Text": "email", 
     "Visible": true 
    }, 
    { 
     "Name": "hiddenField", 
     "Text": "text", 
     "Visible": true 
    } 
    ], 
    "Name": "form2", 
    "Type": "Form" 
} 

EDIT2: Prüfung es heraus bei http://jsfiddle.net/faloi/4FcAy/10/

+0

Können Sie den Code in diesem jsfiddle mit Ihrem Code ersetzen: http://jsfiddle.net/JasonMore/LKS5b/ Ich wette, ich kann Ihnen helfen, sobald ich die JS Laufen zu sehen. –

+0

@JasonMore jsfiddle hinzugefügt! – faloi

Antwort

6

Ich denke, dies ist jetzt die am häufigsten gestellte Frage zum Mapping-Plugin. Das Plugin kann derzeit nur teilweise Aktualisierungen von Eigenschaften vornehmen. ZB wenn Sie die folgenden Daten Ihrem Objekt zuordnen würden:

{ "Name": "pagina1 foo", "Title": "Probando el KO bar" } 

Es würde nur diese Eigenschaften aktualisieren. Allerdings werden die Sammlungen anders behandelt, wenn Sie mit den unten aufgeführten neu zuordnen.

Es würde das nicht übereinstimmende Element in Ihrer Controls-Auflistung entfernen, anstatt das übereinstimmende Element zu aktualisieren. Die einzige Möglichkeit, dies zum Laufen zu bringen, besteht darin, die Sammlung durchzublättern und jeden einzelnen Artikel zuzuordnen, den Sie aktualisieren möchten. Ihr Code ist fast auf dem richtigen Weg Ich glaube es

sein sollte
ko.mapping.fromJS(updatedControl, viewModel.Controls()[0]) 

EDIT

Sie fehlten die mittlere Abbildungs ​​Argument auf die fromJS nennen.

http://jsfiddle.net/3CtFq/

Das Mapping-Objekt in der Regel optional ist, aber ich denke, wenn man ein Unterobjekt zuordnen, wie der Fall ist, kann das Plugin nicht sagen, dass diese Unterpunkte Eltern ursprünglich ohne Optionen abgebildet wurden.

Hoffe, das hilft.

+0

Ich habe versucht mit 'ko.mapping.fromJS (updatedControl, viewModel.Controls() [0])' aber nicht funktioniert ... es ist seltsam, weil 'viewModel.Controls() [0]' tatsächlich das erste zugeordnete Steuerelement zurückgibt – faloi

+0

@faloi - Wenn Sie in eine Datei verschieben können, würde es uns leichter machen, das zu korrigieren, was falsch ist. – madcapnmckay

+0

hinzugefügt jfiddle! – faloi

0

Ich dachte, das war der Sinn der "Schlüssel" -Option. Ich bin mir bewusst, dass es Vorbehalte gegen diese Art von Feature gibt, aber ich bin überrascht, dass es überhaupt keine Unterstützung dafür gibt.

Wie auch immer - das ist (bedauerlicherweise) das, was ich tun musste, um eine Liste von Aufträgen teilweise zu aktualisieren - das heißt, Elemente durchzugehen und zu ersetzen.

data ist mein Haupt AJAX/JSON-Modell aus dem Server und enthält data.orders die ko.observableArray([]) von OrderViewModel Artikel ist. Es enthält auch alle möglichen anderen Sachen data.products, data.foo, die ich anfänglich zuordnen möchte.

Ich habe eine Zuordnungsregel, um neue OrderViewModel Objekte automatisch während des Mapping-Prozesses zu erstellen.

Wenn ich die Daten vom Server zurück bekomme, möchte ich zunächst eine vollständige Abbildung meines Modells machen. Also setze ich initialUpdate=true.

Wenn ich eine einzelne Bestellung aktualisieren möchte, habe ich initialUpdate=false.

 if (initialUpdate) 
    { 
     // standard initial mapping 
     ko.mapping.fromJS(data, mapping, this); 
    } 
    else 
    { 
     // merge orders 
     var newModel = ko.mapping.fromJS(data, mapping); 

     // go through all orders in the updated list 
     for (var i = 0; i < newModel.orders().length; i++) 
     { 
      var newOrder = newModel.orders()[i]; 

      // find order with same key in existing ko model 
      var match = ko.utils.arrayFirst(this.orders(), function (item) 
      { 
       return newOrder.orderId() === item.orderId(); 
      }); 

      if (match == null) 
      { 
       // TODO: insert new order        
      } 

      // replace original order in list 
      this.orders.replace(match, newOrder); 
     } 
    }