【问题标题】:Knockout validation: Dynamic constraints淘汰赛验证:动态约束
【发布时间】:2013-06-23 05:17:45
【问题描述】:

我正在使用 Durandal,而后者又利用了 Knockout。

我希望能够动态更改验证长度

Fiddle

小提琴似乎与我的“工作”解决方案略有不同,但它仍然没有做我想要/期望的事情。

Viewmodel JS:

[尝试 1]

define(function () {

   var self = this;

   self.userInfo = {       
        IdOrPassportNumber: ko.observable().extend({
            required: true,
            pattern: {
                message: 'A message',
                params: /some regex/
            }
        }),
        IdType: ko.observable()
    },

    self.isIdValid = ko.validatedObservable({ 
         IdOrPassportNumber: self.userInfo.IdOrPassportNumber 
    });

    self.userInfo.IdOrPassportNumber.subscribe(function (value) {
          if (isIdValid.isValid()) {
               console.log('YOLO!');
          }
    });

    self.userInfo.IdType.subscribe(function (value) {
        console.log(value);
        if (value === 'Passport') {
            self.userInfo.IdOrPassportNumber.extend({ maxLength: 15 });
        } else {
            self.userInfo.IdOrPassportNumber.extend({ maxLength: 13 });
        }
    });    

    var viewModel = {
        userInfo: self.userInfo
    };

    viewModel["errors"] = ko.validation.group(viewModel.userInfo);
    viewModel["errors"].showAllMessages();

    return viewModel;
});

似乎正在发生的事情是,当我开始输入时,我得到了 13 的最大和最小验证,但是如果我继续输入验证更改为 15。我尝试了另一种方法,在初始可观察扩展 EG,就在正则表达式之后,然后设置最小和最大长度以使用可观察,但没有成功。

[尝试 2]

   self.userInfo = {       
       IdOrPassportNumber: ko.observable().extend({               
            maxLength: self.maxLength(), 
            minlength: self.maxLength()
       }),
       IdType: ko.observable()
   },

   self.maxLength = ko.observable();

   self.userInfo.IdType.subscribe(function (value) {

          if (value === 'Passport') {
             self.maxLength(15)
          } else {
              self.maxLength(3)
          }
    });

【问题讨论】:

  • 能不能用cdnjs.com来抢淘汰验证插件...
  • 完成。 +1 Ps 非常酷的网站。肯定收藏了:)

标签: knockout.js knockout-2.0 durandal knockout-validation


【解决方案1】:

这是对我有用的解决方案:

我使用了custom validation 功能,更具体地说是 single use custom validation 因为这不会在其他地方重复使用。

[尝试 3]

    self.userInfo = {    
        IdOrPassportNumber: ko.observable().extend({
            required: true,
            pattern: {
                message: 'A message',
                params: /some regex/
            },
            validation: {
               validator: function (val) {
                   if (self.userInfo.IdType() === 'Id') { 
                      return val.length === 13; 
                   } else { 
                      return val.length === 15; 
                   }
                },
               message: function () {
                  if (self.userInfo.IdType() === 'Id') {
                    return 'Required: 13 characters';
                  } else {
                    return 'Required: 15 characters';
                  }
               }
            }
        })
     }

【讨论】:

  • 作为旁注。我注意到验证的顺序也很重要,所以假设您希望您的自定义验证器(或任何其他)首先触发,请相应地对它们进行排序
  • <input type="text" data-bind="value: idType()==='Id' ? id : password" />页面上使用两个不同的字段进行固定验证并更改绑定不是更好吗?保存时只需写var idOrPassword=id()||password()
【解决方案2】:

你是如此接近:-) 您必须提供 observable 本身,而不是展开的值。因此,只需从 maxLength() 中删除 () - 验证库会自动为您解包。

self.userInfo = {       
   IdOrPassportNumber: ko.observable().extend({               
        maxLength: self.maxLength, 
        minlength: self.maxLength
   }),
   IdType: ko.observable()
},

这是另一个使用动态正则表达式模式的示例。

    zipPostalPattern = ko.pureComputed(() => this.countryCode() === 'US' ? '^\\d{5}(?:[-\\s]\\d{4})?$' : '');
    zipOrPostal: KnockoutObservable<string> = ko.observable('').extend(
    {
        required: true,
        pattern: {
            message: 'This is not a valid postcode for the country',
            params: this.zipPostalPattern
        }
    });

或(如果您不想要消息)。

    zipPostalPattern = ko.pureComputed(function() { return this.countryCode() === 'US' ? '^\\d{5}(?:[-\\s]\\d{4})?$' : ''});
    zipOrPostal: KnockoutObservable<string> = ko.observable('').extend(
    {
        required: true,
        pattern:  self.zipPostalPattern
    });

重要提示:如果您不想要自定义消息,请不要只删除message 参数并留下pattern = { params: this.zipPostalPattern },因为它不起作用。如果您没有消息,则必须直接为 pattern 参数设置正则表达式/字符串。

当然,您也可以在适当的位置定义计算的 observable(这里可以将 countryCode() 作为函数调用,因为这就是计算的工作方式)

    zipOrPostal: KnockoutObservable<string> = ko.observable('').extend(
    {
        required: true,
        pattern:  ko.pureComputed(function() { 
                     return self.countryCode() === 'US' ? '^\\d{5}(?:[-\\s]\\d{4})?$' : ''
                  })
    });

【讨论】:

  • 对于其他阅读本文的人。我无法针对我在那个阶段遇到的这种确切情况进行测试(不再在这个项目中)。我确实更喜欢@Simon_Weaver 的解决方案作为公认的解决方案,并将其标记为这样。
  • 谢谢。我不得不说我今天才想到我可能能够将一个可观察对象作为参数传递给一个规则,我非常兴奋 - 然后意识到它可能不起作用 - 但后来我再次兴奋起来,它似乎工作得很好 :-) 据我记得它没有明确记录,但如果您已经知道如何使用 Knockout 并增加了一些很大的灵活性,这将非常容易。
【解决方案3】:

考虑一下

self.iDNumber = ko.observable('').extend({
        required: {
            params: true,
            message: 'ID Number is a required field.',
            insertMessages: false
        },
        SouthAfricanIDNumber: {
            message: 'Please enter a valid South African ID number.',
            onlyIf: function() {
                return self.identityType() === 'SAID';
            }
        }
    });

其中 SouthAfricanIDNumber 是使用正则表达式的自定义验证。

【讨论】:

  • 欢迎来到 SO :),但请参阅我接受的答案。 (我不再参与该项目。但我会记住它以备将来使用)
  • +1 以鼓励spacerogue 发布他/她的第一篇文章。
猜你喜欢
  • 2015-02-03
  • 2017-09-26
  • 2023-03-09
  • 2012-02-18
  • 2013-01-29
  • 2011-08-09
  • 2012-12-25
  • 2013-02-18
  • 2012-11-04
相关资源
最近更新 更多