2013-06-05 17 views
9

私はいくつかの必須属性を持つ単純なビューモデルを持っています...対応するプロパティが有効ではない場合、各入力を赤く強調したいが、ページが最初にロードされたときに表示されます。値が変更されたとき、またはユーザーが保存/続行しようとしたときのみ...ノックアウト検証が初期ロード時に評価されないようにする

データバインドを指定しているため、 = "css:{error:name.isValid()== false}"、しかしこれを動的に動作させる他の方法はわかりません...

var foo = { name: ko.observable().extend({required: true}) }; 

<div data-bind="css: { error: !name.isValid() }"> 
    <input type="text" data-bind="value: name" /> 
</div> 

この作品を作る方法に関するアイデアは感謝しています...ありがとう!

答えて

2

を取り、ここで私が思いついた解決策は以下のとおりです。

var Foo = function() 
{ 
    this.name = ko.observable().extend({required: true}).isModified(false); 
    this.validate: function() 
    { 
     if (!this.isValid()) 
     { 
      //... loop through all validated properties and set .isModified(true) 
      return false; 
     } 
     return true; 
    }; 
    ko.validation.group(foo); 
}; 

var Bar = function() 
{ 
    this.foo = new Foo(); 
    this.errors = ko.observableArray([]); //<-- displays errors for entire page 
    this.save = function() 
    { 
     if (!this.foo.validate()) 
     { 
      this.errors(ko.toJS(this.foo.errors())); 
     } 
    }; 
} 

ko.applyBindings(new Bar()); 
ここ

とは、マークアップです...

<div data-bind="with: foo"> 
    <div class="control-group" 
     data-bind="css: { error: name.isModified() && !name.isValid() }"> 
     <label class="control-label">Name<span class="help-inline">*</span></label> 
     <div class="controls"> 
      <input type="text" class="input-block-level" placeholder="Name" 
        data-bind="value: name, event: { blur: function() { name.isModified(true); }}" /> 
     </div> 
    </div> 

    <div class="alert alert-error" 
     data-bind="visible: $parent.errors().length > 0"> 
     <h5>Errors!</h5> 
     <ul data-bind="foreach: $parent.errors()"> 
      <li data-bind="text: $data"></li> 
     </ul> 
    </div> 
</div> 

<button type="submit" class="btn btn-primary" data-bind="click: save">Save</button> 

、ここでは、CSS

.error { color: Red; font-weight: bold; } 
.help-inline { display: none; } 
.error .help-inline { display: inline-block; } 
.error input { border-color: Red; } 
5

より良い方法は、要素をvalidationElementクラスで装飾するようにノックアウト検証を構成することです。これは、この設定オプション追加することによって行われます:あなたは親要素を飾るために必要がある場合は

ko.validation.configure({ decorateElement: true }); 

Click here to see a jsfiddle demonstrating this.

**** QUESTIONのASKERからのコメントに反応してEDIT、***

を、よりエレガントで再利用可能なソリューションは、このカスタムバインディングを親要素に適用することです。

Javascriptを

ko.bindingHandlers.parentvalElement = { 
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     var valueIsValid = valueAccessor().isValid(); 
     if(!valueIsValid && viewModel.isAnyMessageShown()) { 
      $(element).addClass("parentError"); 
     } 
     else { 
      $(element).removeClass("parentError"); 
     } 
    } 
}; 

そしてそうのようなあなたのHTMLに結合適用:

<form data-bind='submit:OnSubmit'> 
    <label data-bind='parentvalElement:name'> 
     <span>Name</span> 
     <input data-bind="value: name" /> 
    </label> 
    <input type='submit' value='submit' /> 
<form> 

が見そうat this updated jsfiddle to see it in action.

+0

で申し訳ありませんが、私の例を簡略化する私の努力に、私はだと取り残さ実際には変更しなければならない他の子/兄弟要素(例:ラベルの色と "*"の視認性)があるので、input要素自体ではなく、 "error"クラスでparent-divを実際に飾るので、これはうまくいかない私のためには、私は〜への道を考え出したと思う私のCSSバインディングロジック(以下を参照)で.isModified()がチェックされているかどうかを確認します。 –

+0

私は私の答えを次のように追加しました。よりシンプルで再利用可能なソリューションは、親要素を飾る....それを試してみてください! – RodneyTrotter

+0

私はバインディングハンドラを作成することなく動作させることができました...私の解決策について私が気に入らない部分は、手動でビューモデルプロパティをループしてisModified(true )ので、私の外側のオブジェクトが.save()を呼び出すと、無効であるが変更されていないフィールドにエラー状態が表示されるようになります。 –

関連する問題