2016-07-06 12 views
0

ノックアウト検証ライブラリを使用せずに独自の検証を作成しようとしています。私はそれが欲しいすべてのタイプのバリデーションを行うことができる共通のバリデーションエクステンダを作成しようとしています。これは、検証のタイプと必要なフラグをオブジェクトのエクステンダに渡すことで行います。問題は、PasswordVisibleプロパティが変更されたときではなく、Passwordフィールドが変更されたときにのみvalidateメソッドが起動することです。これは、パスワードがすでに空で、PasswordVisibleプロパティが変更されたときに、パスワードを空にする試みが変更とみなされず、したがってエクステンダを起動しないときに問題を引き起こしています。別の計算された観測値が変更されたときに、1つの観測可能なカスタムエクステンダを起動する

<!DOCTYPE html> 

<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <meta charset="utf-8" /> 
    <title></title> 
</head> 
<body> 
    <script type="text/javascript" src="knockout-3.4.0.js"></script> 

    Name:<input type="text" data-bind="value:Name" /><br /> 
    Already A User: <input type="checkbox" data-bind="checked:AlreadyUser" /><br /> 
    New Password:<input type="password" data-bind="value:Password,visible:PasswordVisible" /><br /> 
    <input type="button" value="Submit" onclick="validateModel();" /> 

    <script type="text/javascript" > 
     var pageModel; 

     ko.extenders.Validate = function (target, validateOptions) { 
      target.HasErrors = ko.observable(false); 
      var required = validateOptions.required(); 
      var validationType = validateOptions.validationType; 
      function validate(newValue) { 
       alert('validating'); 
       if (required) { 
        switch (validationType) { 
         case "Text": 
          target.HasErrors(newValue == "" ? false : true); 
          break; 
         default: 
          target.HasErrors(false); 
          break; 
        } 
       } 
      } 

      validate(target()); 
      target.subscribe(validate); 
      return target; 
     }; 

     //The model itself 
     var ViewModel = function() {    
      var self = this; 
      self.Name = ko.observable(''); 
      self.AlreadyUser = ko.observable(false); 
      //computed variable that sets the visibility of the password field. I have to clear the password when am making it invisible 
      self.PasswordVisible = ko.computed(function() { return !this.AlreadyUser(); }, this).extend({ notify: 'always' }); 
      //this field is only required when visible 
      self.Password = ko.observable('').extend({ Validate: { required: function() { return self.PasswordVisible() }, validationType: "Text" } }); 
      self.PasswordVisible.subscribe(function (newVal) { self.Password(''); }); 
      self.HasErrors = ko.computed(function() { return self.Password.HasErrors(); },self); 
     }; 



     //The method calls on click of button 
     function validateModel() { 
      alert(pageModel.HasErrors()); 
      } 

     //create new instance of model and bind to the page 
     window.onload = function() {   
      pageModel = new ViewModel(); 
      ko.applyBindings(pageModel); 
     }; 

    </script> 
</body> 
</html> 

PasswordVisibleも変更された場合の検証方法。

答えて

1

HasErrorsko.computedにすると、使用している観測対象のサブスクリプションを自動的に作成できます。それはあなたにもそれを実行するための機能でPasswordVisibleに観察をラップする必要はありませんいくつかの不要な再評価けれども...

ko.extenders.Validate = function(target, validateOptions) { 
    target.HasErrors = ko.computed(function() { 
    // Create subscription to newValue 
    var newValue = target(); 

    // Create subscriptions to any obs. used in required 
    var required = validateOptions.required(); 
    var validationType = validateOptions.validationType; 

    if (ko.unwrap(required)) { 
     switch (validationType) { 
     case "Text": 
      return newValue == ""; 
     } 
    }; 


    return false; 
    }, null, { 
    deferEvaluation: true 
    }); 

    return target; 
}; 

注意をトリガー可能性があります。代わりにko.unwrapを使用できます。

ここで私のアプローチはあなたのコードです。内部に値があるときにパスワードを隠すと、複数の検証をもう一度見てみることもできます(self.Password('')をクリアすると別の検証がトリガーされます)。返信用

var pageModel; 
 
var i = 0; 
 
ko.extenders.Validate = function(target, validateOptions) { 
 
    target.HasErrors = ko.computed(function() { 
 
    console.log("validating " + ++i); 
 

 
    // Create subscription to newValue 
 
    var newValue = target(); 
 

 
    // Create subscriptions to any obs. used in required 
 
    var required = validateOptions.required(); 
 
    var validationType = validateOptions.validationType; 
 

 
    if (ko.unwrap(required)) { 
 
     switch (validationType) { 
 
     case "Text": 
 
      return newValue == ""; 
 
     } 
 
    }; 
 

 

 
    return false; 
 
    }, null, { 
 
    deferEvaluation: true 
 
    }); 
 

 
    return target; 
 
}; 
 

 
//The model itself 
 
var ViewModel = function() { 
 
    var self = this; 
 
    self.Name = ko.observable(''); 
 
    self.AlreadyUser = ko.observable(false); 
 
    //computed variable that sets the visibility of the password field. I have to clear the password when am making it invisible 
 
    self.PasswordVisible = ko.computed(function() { 
 
    return !this.AlreadyUser(); 
 
    }, this).extend({ 
 
    notify: 'always' 
 
    }); 
 
    //this field is only required when visible 
 
    self.Password = ko.observable('').extend({ 
 
    Validate: { 
 
     required: function() { 
 
     return self.PasswordVisible() 
 
     }, 
 
     validationType: "Text" 
 
    } 
 
    }); 
 
    self.PasswordVisible.subscribe(function(newVal) { 
 
    self.Password(''); 
 
    }); 
 
    self.HasErrors = ko.computed(function() { 
 
    return self.Password.HasErrors(); 
 
    }, self); 
 
}; 
 

 

 

 
//The method calls on click of button 
 
function validateModel() { 
 
    console.log(pageModel.HasErrors()); 
 
} 
 

 
//create new instance of model and bind to the page 
 
window.onload = function() { 
 
    pageModel = new ViewModel(); 
 
    ko.applyBindings(pageModel); 
 
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 

 
Name: 
 
<input type="text" data-bind="value:Name" /> 
 
<br />Already A User: 
 
<input type="checkbox" data-bind="checked:AlreadyUser" /> 
 
<br />New Password: 
 
<input type="password" data-bind="value:Password,visible:PasswordVisible" /> 
 
<br /> 
 
<input type="button" value="Submit" onclick="validateModel();" />

+0

こんにちは感謝。それはうまく動作します。同意する。私はそれを一度しか発火させない方法を見ます。もし私がここに別の質問を投稿するのであれば、 '!=。 'ではなく' newValue ==' ''を返さなければならない計算された' HasErrors'変数にはちょっとした訂正があります。それ以外の人はそれを欲しがる。 – Ramki

+0

私は遅延エクステンダを追加してこれを解決しました。以下のように 'extend({deferred:true}') – Ramki

関連する問題