【问题标题】:knockout unable to extend multiple observable using extender淘汰赛无法使用扩展器扩展多个可观察对象
【发布时间】:2016-11-09 06:41:45
【问题描述】:

这与我的另一个问题here有关! 我正在尝试在不使用验证库的情况下创建自定义验证扩展器。

我无法将我的扩展器扩展到多个 observable。在下面的场景中,扩展器应用于密码字段,而不是重新输入密码字段。

<!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>

【问题讨论】:

  • 我已经成功解决了这个问题

标签: knockout.js knockout-validation


【解决方案1】:

我将您的代码复制到交互式 sn-p 中,并注意到出现控制台错误...此外,并非您的 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();" />

【讨论】:

  • 哎呀。对不起,我的坏事......我的 IE 中的 JS 调试已关闭。
猜你喜欢
  • 1970-01-01
  • 2013-05-25
  • 2013-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-26
  • 1970-01-01
相关资源
最近更新 更多