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

knockout无法使用extender扩展多个observate

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

    这与我的另一个问题有关 here ! 我正在尝试创建一个自定义验证扩展程序,而不使用验证库。

    无法将扩展器扩展到多个可观察对象。在下面的场景中,扩展程序应用于“密码”字段,但不应用于“重新键入密码”字段。

    <!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 />
        Password:<input type="password" data-bind="value:Password,visible:PasswordVisible" /><br />
        Retype Password:<input type="password" data-bind="value:RetypePassword,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.computed(function () {
                    var newValue = target();
    
                    var required = validateOptions.required();
                    var validationType = validateOptions.validationType;                
    
                    if (ko.unwrap(required)) {
                        switch (validationType) {
                            case "Text":
                                return newValue == '';
                           default:
                                target.HasErrors(false);
                                break;
                        }
                    }
                    return false;
                }, null, { deferEvaluation: true }).extend({ notify: 'always' });            
                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.RetypePassword = ko.observable('').extend({ Validate: { required: function () { return self.PasswordVisible(); }, validationType: "Text" } });                        
                self.AlreadyUser.subscribe(function (newVal) {  self.RetypePassword(''); });
                self.HasErrors = ko.computed(function () { return self.Password.HasErrors() && self.RetypePassword.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>
    
    1 回复  |  直到 9 年前
        1
  •  1
  •   user3297291    10 年前

    我将您的代码复制到一个交互式代码段中,并注意到有一个控制台错误…此外,您的 computed 返回了一个值。

    我已经解决了这些问题,一切都如你所料。发布前你检查过控制台吗?

    • newValue

    计算错误:

    • 您必须通过调用 target() 在computed方法中
    • 您通过返回值而不是通过 computedObs(newVal) 在…内 方法。

    var pageModel;
    
    ko.extenders.Validate = function(target, validateOptions) {
      target.HasErrors = ko.computed(function() {
        var required = validateOptions.required();
        var validationType = validateOptions.validationType;
        var newValue = target();
        
        if (ko.unwrap(required)) {
          switch (validationType) {
            case "Text":
              return newValue == '';
            default:
              return false
          }
        }
        return false;
      }, null, {
        deferEvaluation: true
      }).extend({
        notify: 'always'
      });
      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.RetypePassword = ko.observable('').extend({
        Validate: {
          required: function() {
            return self.PasswordVisible();
          },
          validationType: "Text"
        }
      });
      self.AlreadyUser.subscribe(function(newVal) {
        self.RetypePassword('');
      });
      self.HasErrors = ko.computed(function() {
        return self.Password.HasErrors() && self.RetypePassword.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);
    };
    .has-error {
      background:red;
    }
    <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 />Password:
    <input type="password" data-bind="value:Password, visible:PasswordVisible, css: {'has-error': Password.HasErrors }" />
    <br />Retype Password:
    <input type="password" data-bind="value:RetypePassword,visible:PasswordVisible, css: {'has-error': RetypePassword.HasErrors }" />
    <br />
    <input type="button" value="Submit" onclick="validateModel();" />
    推荐文章