2011-12-29 12 views
33

Knockoutjs Webサイトのマッピングプラグインの例を使って作業しています。Knockout JSマッピングプラグインを使用して作成したビューモデルにプロパティを追加する

これはサンプルデータです。

Knockout JS Mapping Plugin

var data = { 
    name: 'Scott', 
    children: [ 
     { id : 1, name : 'Alice' } 
    ] 
} 

の例では、子の1つのマッピングを上書きする方法を示していますが、どのように私は、ベースオブジェクトのマッピングを変更します。

たとえば、「FavouriteChild」プロパティをScottに追加する場合は、どうすればよいですか?

基本マッピングでcreate関数を使用する必要があると仮定しますが、どこでも構文の例は見つかりません。

var myChildModel = function(data) { 
    ko.mapping.fromJS(data, {}, this); 

    this.nameLength = ko.computed(function() { 
     return this.name().length; 
    }, this); 
} 

var mapping = { 
    'children': { 
     create: function(options) { 
      return new myChildModel(options.data); 
     } 
    } 
} 

var viewModel = ko.mapping.fromJS(data, mapping); 

EDIT:受け入れ答えからは、私は、これは

<span data-bind='text: AdditionalProperty'> 

var mapping = { 
    create: function (options) { 
     //customize at the root level. 
     var innerModel = ko.mapping.fromJS(options.data); 

     innerModel.AdditionalProperty = 'Hello World'; 

     return innerModel; 
    } 
} 

var viewModel = ko.mapping.fromJS(data, mapping); 

//use this as our model bindings 
ko.applyBindings(viewModel); 

答えて

23

あなたはマッピングオブジェクト自体にcreateメソッドを使用する必要がノックアウトコードを機能することがわかっ下回りますlike:

var mapping = { 
    //customize at the root level. 
    create: function(options) { 
    //first map the vm like normal 
    var vm = ko.mapping.fromJS(options.data); 

    //now manipulate the returned vm in any way that you like 
    vm.someProperty = "test"; 

    vm.someComputed = ko.computed(function() { 
      return vm.first() + " " + vm.last(); 
    }); 

    //return our vm that has been mapped and tweaked 
    return vm; 
    } 
}; 
ここで
+6

レベルに追加して追加します。 –

+0

は、返す前に結果をマップして操作する方法を示す関数を更新しました。 –

+0

私はこれが非常に古い質問であることを知っていますが、ちょうどそれに出くわして私は提案をしたかった。マッピング時にCreateコールバックを使用するコードサンプル(KnockoutJsサイトで)は、createメソッドがマッピングオブジェクトにあることを説明していません。 Ryan、可能であれば、私はサイトの所有者にあなたのコードサンプルをあなたのものと置き換えるよう依頼します。 –

13

はRPニーマイヤーのソリューション

に基づいて、この答えに継続され、ここで上記と自身のブログからのソリューションに基づいています。この答えは - それをありがとう!配列が最初のレベルのオブジェクトではないときにアドレスするため、いくつかの詳細を追加する必要があると思いました。

var data = { 
person: { 
     children: [{ id: 1, firstName: 'Scot', lastName: 'Weise'}] 
    } 
}; 

var mapping = { 
    'children': { 
     create: function(options) { 
      return (new (function() { 
       // setup the computed binding for some reason I had 
       // to use ko.dependentObservable instead of ko.computed 
       // or errors showed up. 
       this.fullName = ko.dependentObservable(function() { 
        return this.firstName() + ' ' + this.lastName(); 
        }, this); 
        ko.mapping.fromJS(options.data, { }, this); 
       })(/* call the ctor here */)); 
      } 
     } 
    }; 

    // Create view model and map the data object to the model. 
    var viewModel = ko.mapping.fromJS(data, {}); 

    // update the viewModel with the mapping object that contains 
    // some a computed property(s) 
    viewModel.person = ko.mapping.fromJS(viewModel.person, mapping); 
    ko.applyBindings(viewModel); 

人物は第1レベルのオブジェクトであり、子はその人物のサブプロパティであることに注意してください。 viewModel.person = ko.mapping.fromJS(viewModel.person、mapping)という行は、当初私にとっては直感的ではありませんでした。

そしてここにはわずかな変化である

人物オブジェクトは、もともとは、サーバーのJSONデータから作成された後に追加または更新された観測可能です。

var viewModel = {}; 
$(document).ready(function() { 
    var person = getPerson(); 

    // selected person is added to the viewModel 
    viewModel.selectedPerson = ko.observable(person); 
    ko.applyBindings(viewModel); 
}); 

function getPerson() { 
// you would probably pass this into the function as a parameter. 
var person = 
    { 
     name: 'jim', 
     children: [{ id: 1, firstName: 'jane', lastName: 'bob'}] 
    }; 

    var mapping = { 
     'children': { 
      create: function (options) { 
       return (new (function() { 
        // setup the computed binding 
        this.fullName = ko.dependentObservable(function() { 
        return this.firstName() + ' ' + this.lastName(); 
        }, this); 
        ko.mapping.fromJS(options.data, {}, this); 
       })(/* call the ctor here */)); 
      } 
     } 
    }; 

    var result = ko.mapping.fromJS(person, mapping); 
    return result; 
} 

HTML

の一部の結合コード最終的には、次のようないくつかの点でいくつかの使用にそれを置く必要があります:

<div data-bind="foreach:viewModel.selectedPerson().children"> 
    <span data-bind="text:fullName"></span> 
</div> 

あなたの助けに感謝!私はあなたのブログの投稿なしでこれまでこれを作っていない可能性があります。子供に追加計算された観測を定義するための

3

注あなたはマッピングオプション

var mapping = { 
    create: function(options) { 
    //customize at the root level. 

    var mapping2 = { 
     'children': { 
     create: function(options) { 
      //customize children also 

     } 
     } 
    } 

    //call ko.mapping.fromJS on the options.data as well with further customization 
    ko.mapping.fromJS(options.data, mapping2, this); 
    } 
}; 
+1

私はネストされたプロパティをマップする方法を探していましたが、これは最も明確な例でした。それがviewModelのサンプルを含んでいれば、それは私のための完全な解決策になります。 –

0

ジェイソンとRPニーマイヤーによって提供されている例に基づいて、別の例の別のセットを渡す必要があります。

dataは、我々は2つの入れ子観測(viewModel.weekly.selectedWeekviewModel.monthly.selectedMonth)を追加した上で、Ajaxのクエリの後に取得されるものです。説明についてはどのように、空の機能で作成し、そのルートへのアクセスについては何も示していない方法

var data = { 
     "date": "2017-03-28", 
     "weekly": { 
      "weeks": [ 
       { 
        "id": "201701", 
        "label": "Week 1" 
       }, 
       { 
        "id": "201702", 
        "label": "Week 2" 
       } 
      ] 
     }, 
     "monthly": { 
      "months": [ 
       { 
        "id": "201701", 
        "label": "01/2017" 
       }, 
       { 
        "id": "201702", 
        "label": "02/2017" 
       } 
      ] 
     } 
    } 

    var viewModelMapping = { 
     create: function (options) { 
      return (new (function() { 
       // viewModel root level 
       var mapping2 = { 
        'weekly': { 
         create: function (options) { 
          // viewModel.weekly 
          return new function() { 
           var model = ko.mapping.fromJS(options.data, {}, this); 
           model.selectedWeek = ko.observable(); 
           return model; 
          }; 
         } 
        }, 
        'monthly': { 
         create: function (options) { 
          // viewModel.monthly 
          return new function() { 
           var model = ko.mapping.fromJS(options.data, {}, this); 
           model.selectedMonth = ko.observable(); 
           return model; 
          }; 
         } 
        } 
       }; 

       ko.mapping.fromJS(options.data, mapping2, this); 
      })()); 
     } 
    }; 


    var viewModel = ko.mapping.fromJS(data, viewModelMapping); 
    ko.applyBindings(viewModel); 
関連する問題