6

現在、この JSON を KO Mapping プラグインで使用していますが、問題なく動作しています。

{
  "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"
}

今、私の要件は「部分的な更新」を実行することです。私がそれをしたいときのいくつかのシナリオ:

  • 2 番目のコントロールの Data 配列を変更する必要があります。
  • ページ全体ではなく、1 つのコントロールのみを更新する必要があります (これは、シリアル化するクラスであり、この JSON のルートです)。
  • ページに別のコントロールを追加する必要があります。

おそらく別の回避策は、元のオブジェクトを で再作成しko.mapping.toJS(viewModel)、変更してから再度マップすることです...しかし、より良いものが出てくると思います。


編集:試してみましko.mapping.fromJS(updatedControl, viewModel.Controls()[0])たが、うまくいきませんでした。これが私のコードです:

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

応答:

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

EDIT2: http ://jsfiddle.net/faloi/4FcAy/10/でチェックしてください

4

2 に答える 2

6

これは、マッピング プラグインに関して最もよく聞かれる質問の 1 つだと思います。プラグインは現在、プロパティの部分的な更新のみを行うことができます。たとえば、以下のデータをオブジェクトに再マップする場合

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

それらのプロパティだけを更新します。ただし、コレクションの扱いが異なるため、以下で再マップする場合。

{ "Name": "pagina1 foo", "Title": "Probando el KO bar", 
  Controls: [ { // snip some updated object } ] }

一致するアイテムを更新する代わりに、Controls コレクション内の一致しないアイテムを削除します。これを機能させる唯一の方法は、コレクションをループして、更新する個々のアイテムをマップすることです。あなたのコードはほぼ正しい軌道に乗っているはずです

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

編集

fromJS 呼び出しで中間のマッピング引数がありませんでした。

http://jsfiddle.net/3CtFq/

マッピングオブジェクトは通常オプションですが、あなたの場合のようにサブオブジェクトをマッピングしている場合、プラグインはこのサブアイテムの親が最初にオプションなしでマッピングされたことを伝えることができないと思います.

お役に立てれば。

于 2012-04-18T22:16:27.547 に答える
0

それが「キー」オプションを持つことの要点だと思いました。この種の機能には注意点があることはわかっていますが、まったくサポートされていないことに驚いています。

とにかく-これは(残念ながら)注文のリストを部分的に更新するために私がしなければならなかったことです-それはアイテムをループして置き換えることです.

dataサーバーからの私のメインのAJAX / JSONモデルであり、どれがアイテムであるかが含まれdata.ordersていko.observableArray([])ますOrderViewModeldata.productsまた、data.foo最初にマップしたい他のすべての種類のものも含まれています。

マッピング プロセス中に新しいOrderViewModelオブジェクトを自動的に作成するマッピング ルールがあります。

            var mapping =
            {
                'orders':
                {
                    key: function (item)
                    {
                        return ko.utils.unwrapObservable(item.orderId);
                    },

                    create: function (options)
                    {
                        return new OrderViewModel(options.data);
                    }
                }
            };

サーバーからデータを取得したら、最初にモデルの完全なマッピングを行いたいと思います。だから私は設定しinitialUpdate=trueました。

私が持っている単一の注文を更新したいとき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);
         }
     }
于 2014-07-16T01:32:00.080 に答える