Search code examples
knockout.jsknockout-validation

Clearing the observable when it's invisible


Below is a sample of what am trying to achieve. I need to clear the password in the pagemodel when am making it invisible and am not sure how to do that.

<!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>
    <script type="text/javascript" src="knockout.validation.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();" />

    <script type="text/javascript" >
        var pageModel;
        ko.validation.init({
            registerExtenders: true,
            messagesOnModified: true,
            insertMessages: false,
            parseInputAttributes: true,
            messageTemplate: null
        }, true);

        //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);
            //this field is only required when visible
            self.Password = ko.observable('').extend({ required: { onlyIf: function () { return self.PasswordVisible(); }, message: 'Password Invalid' } });
            self.errors = ko.validation.group(self);                   
        };

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

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

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

I'm not able to clear when I am computing PasswordVisible as the Password property is yet to be created in the order of execution. I cannot swap it as that would cause issues with my extender for required validation.


Solution

  • You could simply do this:

    <input type="password" data-bind="value:Password, visible:AlreadyUser" />
    

    No need for the computed at all. Then in your ViewModel:

    self.Password = ko.observable('').extend({ 
        required: { 
          onlyIf: function () {
            return self.AlreadyUser(); 
          }, 
          message: 'Password Invalid' 
        } 
    });
    

    Edit

    I believe I failed to answer your question in my original answer. If you want to actually clear self.Password() whenever the user unchecks (or checks) the checkbox bound to self.AlreadyUser then you can use subscribe:

    self.AlreadyUser.subscribe(function(newVal){ 
       // reset password every time the value of self.AlreadyUser() changes
       self.Password(''); 
    });