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
Post a Comment