1

私はノックアウトjsを使用して、バックエンドでasp.netmvc4を使用してアプリケーションを構築しています。knockout.mappingを使用して、MVCサービス呼び出しからオブザーバブルにデータを入力しています

次に、Knockout.Validationプラグインを使用して検証を追加しようとしています。

self.sDetail(ko.mapping.fromJS(s));
var validationOptions = { 
                          insertMessages: true, 
                          decorateElement: true,      
                          errorElementClass: 'errorFill' 
                         };
ko.validation.init(validationOptions);
self.sDetail.Year.extend({ required: true });

実行すると、次のエラーが発生します。

Error: Unable to get property 'extend' of undefined or null reference

デバッグすると、sDetailが空になっていることがわかります。ApplyBindingsを適用すると、入力が正しく入力されます。どの時点で、koviewmodelのプロパティにアクセスできます。この問題を回避する方法はありますか?

4

3 に答える 3

2

ここで解決策を見つけました: ノックアウトマッピングの検証

基本的に、マッピングの呼び出しでプロパティを拡張する必要があります

var validationMapping = {
// customize the creation of the name property so that it provides validation
Year: {
    create: function(options) {
        return ko.observable(options.data).extend( {required: true} );
    }
}
};


  self.sDetail(ko.mapping.fromJS(s,validationMapping));
 var validationOptions = { 
                      insertMessages: true, 
                      decorateElement: true,      
                      errorElementClass: 'errorFill' 
                     };
  ko.validation.init(validationOptions);

self.sDetail.Year.extend({必須:true});

于 2013-02-15T00:55:15.860 に答える
1

元のコードの実際の問題はYear、モデル自体ではなく、マップされたモデルを保持しているオブザーバブルのプロパティにアクセスしようとしたことでした(実際のビューモデルであるとしか想定できないsDetailオブザーバブルであると想定しています)。selfこれは私が私のコメントで意味したことでした。オブザーバブルが保持する値をマップしたので、その値を読み取る必要があります。extend()オブザーバブルに存在しないプロパティを試行したため、エラーが発生しました。

self.sDetail; // <- your observable holding the model
self.sDetail.Year; // <- undefined, observables don't have a `Year` property
self.sDetail.Year.extend(...); // <- error

修正は、observableを呼び出して、それが保持するモデルを取得し、その後、必要なものにアクセスできるようにすることです。

self.sDetail().Year.extend({ required: true }); // this should work

これは、最終的なソリューションを損なうものではありません。よりクリーンなコード(IMHO)につながるため、マッピング設定内から拡張することをお勧めします。

于 2013-02-15T01:44:25.253 に答える
1

よりクリーンで読みやすいソリューションについては、明示的に宣言されたVMを使用してください

DetailsViewModel = function(data) {
   this.year = ko.observable().extend({ required: true });
   ko.mapping.fromJS(data, {}, this);
};

のように使用

new DetailsViewModel(data);

実際のドメインロジックを実行するすべてのメンバーを明示的に宣言することをお勧めします。プレゼンテーションのみのメンバーは、ko.mappingによって自動マッピングできます。

更新:いくつかのダウチによって反対票を投じられましたが、このソリューションは非常に有効で読みやすいです

http://jsfiddle.net/hww8vk1n/1/

于 2013-02-15T09:31:06.580 に答える