knockout无法使用扩展器扩展多个可观察对象

时间:2016-07-07 03:25:53

标签: knockout.js knockout-validation

这与我的另一个问题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 个答案:

答案 0 :(得分:1)

我将您的代码复制到交互式代码段,并注意到存在控制台错误...此外,并非computed中的所有路径都返回了值。

我已经解决了这些问题,一切都按照您的预期运作。你在发布之前检查了控制台吗?

错误:

  • newValue未定义

计算错误:

  • 您必须通过调用计算方法
  • 中的target()来创建订阅
  • 您通过返回一个值来“设置”计算,而不是通过 方法中的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();" />