knockout.js - firing custom extender of one observable when another computed observable is changed -


i trying create own validation without using knockout validation library. trying create common validate extender can type of validations want do. doing passing type of validation , required flag in object extender. problem having validate method fires when password field changed , not when passwordvisible property changed. causing problem when password empty , when passwordvisible property changed, attempt empty password not considered change , hence not firing extender.

<!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 />     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         var viewmodel = function () {                         var self = this;             self.name = ko.observable('');             self.alreadyuser = ko.observable(false);             //computed variable sets visibility of password field. have clear password when making invisible             self.passwordvisible = ko.computed(function () { return !this.alreadyuser(); }, this).extend({ notify: 'always' });             //this field 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 , bind page         window.onload = function () {                       pagemodel = new viewmodel();             ko.applybindings(pagemodel);         };      </script> </body> </html> 

how fire validate when passwordvisible changed well.

you make haserrors ko.computed automatically create subscriptions observable used. might trigger unneeded re-evaluations though...

ko.extenders.validate = function(target, validateoptions) {   target.haserrors = ko.computed(function() {     // create subscription newvalue     var newvalue = target();      // create subscriptions 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; }; 

note not need wrap passwordvisible observable in function execute it; can use ko.unwrap instead.

here's approach in code. might want take @ multiple validations once hide password when there's value inside (the clear via self.password('') triggers validation).

var pagemodel;  var = 0;  ko.extenders.validate = function(target, validateoptions) {    target.haserrors = ko.computed(function() {      console.log("validating " + ++i);        // create subscription newvalue      var newvalue = target();        // create subscriptions 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  var viewmodel = function() {    var self = this;    self.name = ko.observable('');    self.alreadyuser = ko.observable(false);    //computed variable sets visibility of password field. have clear password when making invisible    self.passwordvisible = ko.computed(function() {      return !this.alreadyuser();    }, this).extend({      notify: 'always'    });    //this field 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 , bind 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 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();" />


Comments

Popular posts from this blog

sequelize.js - Sequelize group by with association includes id -

android - Robolectric "INTERNET permission is required" -

java - Android raising EPERM (Operation not permitted) when attempting to send UDP packet after network connection -