代码之家  ›  专栏  ›  技术社区  ›  Ramki

当另一个计算的可观测项更改时,触发一个可观测项的自定义扩展程序

  •  0
  • Ramki  · 技术社区  · 10 年前

    我尝试在不使用淘汰验证库的情况下创建自己的验证。我正在尝试创建一个通用的Validate扩展程序,它可以执行我希望它执行的所有类型的验证。我通过将对象中的验证类型和所需标志传递给扩展程序来实现这一点。存在的问题是,validate方法仅在Password字段更改时激发,而不是在PasswodVisible属性更改时激发。当密码已为空并且PasswordVisible属性更改时,尝试清空密码不被视为更改,因此不会触发扩展程序,这会导致问题。

    <!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 回复  |  直到 10 年前
        1
  •  1
  •   user3297291    10 年前

    你可以 HasErrors ko.computed 自动创建对所使用的任何可见项的订阅。但它可能会触发一些不必要的重新评估。。。

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

    请注意,您也不需要将 PasswordVisible 在函数中可以观察到以执行它;你可以使用 ko.unwrap 相反

    这是我在代码中的方法。当密码中有一个值(clearvia 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();" />