2017-07-12 26 views
1

私には、loaddata関数を持つViewモデルがあります。コンストラクタはありません。 IDフィールドに値がある場合は、loadDataメソッドを呼び出す必要があります。フィールドは介して取得されていることをoservableでデータを表示することができません

self.TemplateId = ko.observable($("#InputTemplateId").val()); 

その後、私のViewModelの終わりに、私はあることをチェックするコードのビットを持っている、と私のロード機能を呼び出します。

if (!self.CreateMode()) { 
     self.loadData(); 
    } 

マイロードメソッドは、私の.Net WebAPIメソッドを呼び出します。このメソッドは、非常に複雑な構造体を返します。構造体はクラスであり、いくつかのフィールドと配列/リストがあります。そのリスト内の項目は、いくつかの基本的なフィールドであり、別のリスト/配列です。そして、そのオブジェクトはちょうどいくつかのフィールドを持っています。それで、それは3つのレベルです。オブジェクトのリストを持つオブジェクトとそれらのオブジェクトはそれぞれオブジェクトの別のリストを持っています...

私のWebAPI呼び出しが機能しています。私はそれをデバッグし、データは完全に戻ってきています。

self.loadData = function() { 
     $.get("/api/PlateTemplate/Get", { id: self.TemplateId() }).done(function (data) { 
      self.Data(ko.mapping.fromJS(data)); 

     }); 
    } 

私はこの呼び出しの内容を 'Data'という観測可能オブジェクトにロードしようとしています。これは、以前に宣言されました:

self.Data = ko.observable(); 

私はノックアウトマッピング・プラグインを使用しています、それをロードして、観察可能なすべてのものを維持します。

self.Data(ko.mapping.fromJS(data)); 

私はそれにブレークポイントすると、私は両方のデータに期待するもの(API呼び出しの結果を)見ていて、self.Data()

enter image description here

self.Dataようです私がロードしたデータの観測可能なバージョンとなるようにしてください。すべてのデータがそこにあり、それはすべて正しいようです。

私は、データオブジェクトのルート内のフィールドのいずれかの値に警告することができる午前:

alert(self.Data().Description()); 

は、私はまた、リストの最初の項目内のフィールドを参照することができますよ。

alert(self.Data().PlateTemplateGroups()[0].Description()); 

これは、データが観測可能であり、データを含んでいることを示しています。私は後でself.Dataを私のAPIに送って保存/更新することができると思う。

今、問題が始まります。

私の見解では、私の複雑なアイテムのルートクラスに存在するフィールドを表示しようとしています。ちょうど私が上に警告した何か。

<input class="form-control" type="text" placeholder="Template Name" data-bind="value: Data.Description"> 

エラーは発生しません。それでも、テキストボックスは空です。

私がすべき入力ボックスのコードに変更した場合:

data-bind="value: Data().Description()" 

は、データが表示されます。しかし、私はコンソールでエラーが発生して座っています:

Uncaught TypeError: Unable to process binding "value: function (){return Data().Description() }" Message: Cannot read property 'Description' of undefined

私はko.mappingを使用していますので、データは、したがって、WebAPIの呼び出しからロードされ、前にそれは、ビューの負荷が原因だと思います - ビューには何のData()がないのかわかりません。Description()は...死んでしまいます。

私は何をしようとしているのですか?以下は完全なViewModelです。

function PlateTemplateViewModel() { 
    var self = this; 

    self.TemplateId = ko.observable($("#InputTemplateId").val()); 
    self.CreateMode = ko.observable(!!self.TemplateId() == false); 

    self.IsComponentEditMode = ko.observable(false); 
    self.IsDisplayMode = ko.observable(true); 
    self.CurrentComponent = ko.observable(); 

    self.Data = ko.observable(); 

    self.EditComponent = function (data) { 

     self.IsComponentEditMode(true); 
     self.IsDisplayMode(false); 
     self.CurrentComponent(data); 

    } 
    self.loadData = function() { 
     $.get("/api/PlateTemplate/Get", { id: self.TemplateId() }).done(function (data) { 
      self.Data(ko.mapping.fromJS(data)); 

     }); 
    } 

    self.cancel = function() { 
     window.location.href = "/PlateTemplate/"; 
    }; 

    self.save = function() { 
     var data = ko.mapping.toJS(self.Data); 
     $.post("/api/PlateTemplate/Save", data).done(function (result) { 
      alert(result); 
     }); 
    }; 

    if (!self.CreateMode()) { 
     self.loadData(); 
    } 
} 

$(document).ready(function() { 
    ko.applyBindings(new PlateTemplateViewModel(), $("#plateTemplate")[0]); 
}); 

多分、答えはready()関数内のロードを行い、データをパラメータとして渡すことでしょうか?新しいアイテムを作成したいときに何が起こるかはわかりませんが、私はそれを知ることができます。

さらに、私は保存しようとすると、ビュー内のフィールドを変更する可能性がある(たとえばUpdate Descriptionなど)、観測ビューモデル(self.Data)のデータは変更されません。

+0

あなたは*ルート*ビューモデルにまたはで' Data'に 'Data'プロパティを指すようにしたいData.Description' *各*あなたの 'PlateTemplateGroups'の?つまり、正確に(どの範囲で) 'data-bind = ... 'が存在するのでしょうか?また、 'value:Data()&& Data()。説明&& Data()。説明()'を試してみましたか? – haim770

+0

これを試すことができます:ko.mapping.fromJS(data、{}、self.Data); (http://knockoutjs.com/documentation/plugins-mapping.html、 'アップデートターゲットの指定')。 –

+0

@JoseLuis - 私はそれを試して、私はすべての私のバインドオブジェクトから角括弧を削除する必要がありました。ビューにはデータは表示されません。 this.Dataにはデータがありますが。画面が早すぎると思われるかもしれませんか? – Craig

答えて

1

あなたの入力フィールドは、この可能性:

<div data-bind="with: Data"> 
    <input class="form-control" type="text" placeholder="Template Name" data-bind="value: Description"> 
</div> 

私はそのクリーナーとしてwithを使用して好むとあなたが持った混乱や問題を停止する必要があります。

エラーがあるのは、データがロードされる前にhtmlがすでにバインドされているためです。

$.get("/api/PlateTemplate/Get", { id: self.TemplateId() }).done(function (data) { 
     self.Data(ko.mapping.fromJS(data)); 
     ko.applyBindings(self, document.getElementById("container")); 
    }); 

をまたはデータがもともと定義されていないようので、それはあなたにこのエラーを与えることはありません、ifでテンプレートをラップ:だからどちらかのデータがロードされるまでのバインディングを適用しません。

self.Data = ko.observable(); // undefined 

<!-- ko if: Data --> 
<div data-bind="with: Data"> 
    <input class="form-control" type="text" placeholder="Template Name" data-bind="value: Description"> 
</div> 
<!-- /ko --> 

また、データモデルがどのようになるのかわかっている場合は、デフォルトのデータにすることができます。

self.Data = ko.observable(new Data()); 

適用バインディング方法: `ことで

var viewModel = null; 
$(document).ready(function() { 
    viewModel = new PlateTemplateViewModel(); 
    viewModel.loadData(); 
}); 
+0

私のdocument.Ready - ko.ApplyBindingを削除する必要がありますか?それを私のloadData関数に移動しますか?もしそうなら、決して走らない。あなたのdocumentReadyに – Craig

+0

を置き換えます。ko.applyBindings(viewModel、document.getElementById( "container"));を置き換えます。 viewModel.loadData(); –

+0

くそー、私はそれを試み、同じ結果を得る。私がロードした元のモデルをポストします。更新されたものではありません。フィールドを編集すると、this.Dataが更新されないようです。 – Craig

関連する問題