2016-11-28 5 views
0

私はMVCアプリケーションでKnockout.jsを使用しています。 継承を使用しようとしていますが、各ViewModelインスタンスに対して新しいものが作成される代わりに、BaseViewModelが再利用されている可能性があります。ベースViewModelの同じインスタンスを再利用するノックアウト継承?

私は1つのBaseViewModelとそれを拡張する複数のViewModelを持っています。動作はすべてのViews \ ViewModelsで同じです - アイテムのリストをHTMLテーブルとして表示し、行の編集ボタンをクリックするとモーダルウィンドウで選択した行がポップアップし、その変更を編集して保存できます行。

これらはすべて独立した見解でうまく動作します。しかし、すべてを単一のビューで表示しようとすると、問題が発生しています。

各ビューのリストはすべて結構です。 LASTリスト/テーブルの選択した行の編集をクリックすると正常に動作します。 しかし、FIRSTリスト/テーブルの選択された行の編集をクリックすると、エラーが発生して失敗します。

Uncaught ReferenceError: Unable to process binding "value: function(){return Name }" 

"名前"は、最初のモデルではなく、2番目のViewModelのモデルのプロパティです。

エラーは1つのBaseViewModelしか作成されていないため、Viewに新しいViewModelを追加するたびにそのBaseViewModelのプロパティが上書きされるためです。

問題の例はここにあります。 JSFiddle

editItem関数を見て、コンソールを起動します。 次に、2番目のテーブルのEditをクリックすると、基本クラスに渡された値をコンソールに出力し、Modalウィンドウが正常に表示されます。

あなたが最初のテーブルの編集をキャンセルしてクリックした場合、あなたはそれが第二のViewModelは、それ自体が渡された値をBaseVMに渡され、およびなく、同じ値を出力表示されます。

ここでは私ですBaseViewModelと派生したViewModelをノックアウトします。

EnvironmentAssetBaseViewModel = function(modalWindowName, apiResourceName, modelDefinition) { 
    var self = this; 
    self.modalWindowName = modalWindowName; 
    self.apiResourceName = apiResourceName; 
    self.modelDefinition = modelDefinition; 
    self.itemList = ko.observableArray([]); 
    self.selectedRow = ko.observable(modelDefinition); 

    function getData() { 
     //make ajax API call and store data in itemList 
     var data = []; 
     if (apiResourceName == 'activityLogs') { 
      data = [ 
       { Id: "1", Action: "a", Details: "d"}, 
       { Id: "2", Action: "b", Details: "e"}, 
       { Id: "3", Action: "c", Details: "f"} 
      ] 
     } else { 
      data = [ 
       { Id: "109", Name: "a", Description: "d" }, 
       { Id: "209", Name: "b", Description: "e" }, 
       { Id: "309", Name: "c", Description: "f" } 
      ] 
     } 

     self.itemList(data); 
    } 

    function editItem(item) { 
     console.log(self.modalWindowName); 
     console.log(self.apiResourceName); 
     console.log(self.modelDefinition); 
     self.selectedRow(item); 
     $(modalWindowName).modal('show'); 
    } 

    function cancel(item) { 
     $(modalWindowName).modal('hide'); 
    } 
    return { 
     self: self, 
     itemList: self.itemList, 
     selectedRow: self.selectedRow, 
     getData: getData, 
     editItem: editItem, 
     cancel: cancel 
    } 
}; 



ActivityLogsViewModel = function() { 
    var self = this; 
    var modalName = "#activityLogModal"; 
    var apiResourcename = "activityLogs"; 
    var modelDefinition = { Id: "", Action: "", Details: "" }; 

    ko.utils.extend(self, new EnvironmentAssetBaseViewModel(modalName, apiResourcename, modelDefinition)); 
    getData(); //initial data load 

    return { 
     self: self, 
     editItem: editItem, 
     cancel: cancel 
    } 
}; 
ko.applyBindings(ActivityLogsViewModel, document.getElementById('activityLogsDiv')); 




DomainsViewModel = function() { 
    var self = this; 
    var modalName = "#domainModal"; 
    var apiResourcename = "domains"; 
    var modelDefinition = { Id: "", Name: "", Description: "" }; 

    ko.utils.extend(self, new EnvironmentAssetBaseViewModel(modalName, apiResourcename, modelDefinition)); 
    getData(); //initial data load 

    return { 
    self: self, 
    editItem: editItem, 
    cancel: cancel 
    } 
}; 


ko.applyBindings(DomainsViewModel, document.getElementById('domainsDiv')); 

答えて

0

機能のインスタンスを作成するいくつかの方法を混在させています。

プレーンオブジェクトを「手動で」返すコンストラクタ関数を定義しました。これは完全に問題ありませんが、newというキーワードで呼び出さないことを意味します。

var self = this; 

ファクトリメソッドの呼び出し元のコンテキストがあるものは何でもへselfを設定します:あなたはそれを使用していないので、

newキーワードは、あなたの最初の行を新しいthisコンテキストを作成しますが、。この場合、window

これは、すべてのコンストラクタ関数/ファクトリがwindow名前空間を汚染していることを意味し、不足している/オーバーライドされている不思議なプロパティの組み合わせが発生します。

新しいオブジェクトを作成するにはにvar self = thisを置き換えてください。ビューモデルを作成する関数を呼び出すことを確認してください:var activityVM = ActivityLogsViewModel()

あなたは他のバグ(例えば、getData()self.getData()である必要があります)を実行しますが、それを理解できるはずです。

さらなるヘルプが必要な場合はお知らせください。

+0

ありがとうございました。 var Base = new EnvironmentAssetBaseViewModel(modalName、apiResourcename、modelDefinition)を使用して問題を解決できました。 Base.getData(); var self = {}を使用するようにコードを変更しましたが、既に動作状態になっていたために改善されているかどうかはわかりません。 – RSSM

関連する問題