2016-07-06 1 views
0

Ich versuche, meine eigene Validierung ohne Verwendung der Knockout-Validierungsbibliothek zu erstellen. Ich versuche, einen allgemeinen Validate-Extender zu erstellen, der alle Arten von Validierungen durchführen kann, die ich möchte. Mache dies, indem ich den Validierungstyp und das erforderliche Flag in einem Objekt an den Extender übergebe. Das Problem besteht darin, dass die Validierungsmethode nur ausgelöst wird, wenn das Kennwortfeld geändert wird und nicht wenn die PasswordVisible-Eigenschaft geändert wird. Dies führt zu einem Problem, wenn das Kennwort bereits leer ist und wenn die PasswordVisible-Eigenschaft geändert wird. Der Versuch, das Kennwort zu leeren, wird nicht als Änderung betrachtet und löst daher den Extender nicht aus.feuern benutzerdefinierte Extender von einer beobachtbar, wenn eine andere berechnete Observable geändert wird

<!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> 

Wie wird die Validierung ausgelöst, wenn auch PasswordVisible geändert wird?

Antwort

1

Sie könnten HasErrors eine ko.computed machen, um automatisch Subskriptionen für jede Observable zu erstellen. Es könnte einige nicht benötigte Neubewertungen obwohl auslösen ...

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; 
}; 

Beachten Sie, dass Sie auch die PasswordVisible beobachtbaren in einer Funktion zu wickeln nicht brauchen, um es auszuführen; Sie können stattdessen ko.unwrap verwenden.

Hier ist mein Ansatz in Ihrem Code. Vielleicht möchten Sie einen weiteren Blick auf die Mehrfachvalidierungen werfen, sobald Sie das Passwort verstecken, wenn sich ein Wert darin befindet (das Löschen über self.Password('') löst eine weitere Validierung aus).

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

Hallo Danke für die Antwort. Es funktioniert gut. Ich stimme zu. Ich werde sehen, wie ich es nur einmal feuern kann. Wenn nicht, werde ich hier eine andere Frage stellen. Es gibt nur eine triviale Korrektur für die berechnete 'HasErrors'-Variable, die ich zurückgeben muss' newValue == '' statt '! =.' Wenn Sie korrigieren, wird es für jeden hilfreich sein sonst wer will es geigen. – Ramki

+0

Ich habe das gelöst, indem ich Deferred Extender hinzugefügt habe. wie unten 'extendieren ({deferred: true})' – Ramki

Verwandte Themen