我有以下用于验证名称的类,不允许用户输入空名称。有了它,我可以获取有效值,并在输入无效的情况下通知用户(保留最后的有效值)。

class @Person
  constructor: (name) ->
    @name = ko.observable name
    @nameLastInvalid = ko.observable false
    @nameAttempt = ko.computed
      read: @name
      write: (value) =>
        if value.length > 0
          @name value
          @nameLastInvalid false
        else
          @nameLastInvalid true
      owner: @


我想使相同的功能更可重用。有没有一种方法可以扩展ko.observable对象以添加'lastInvalid'和'attempt'方法?

就像是:

class @Person
  constructor: (name) ->
    @name = ko.observable(name).extend({ required: true })


然后能够做到:

person.name()
person.name().lastInvalid()
person.name().attempt()


AFAIK knockout-validation无法以这种方式工作。它允许您放置无效值,然后告诉您它是否有效。

更新:

我添加了以下扩展器,但它似乎没有做任何事情(我得到了name.attempt是未定义的)

ko.extenders.required = (target, option) ->
  target.lastInvalid = ko.observable false
  target.attempt = ko.computed ->
    read: target
    write: (value) ->
      if value.length > 0
        target value
        target.lastInvalid false
      else
        target.lastInvalid true
  target

最佳答案

扩展程序的局部性不起作用,因为->定义中有一个额外的attempt。因为当您要向计算对象提供读,写功能时,您需要提供对象文字而不是函数:

target.attempt = ko.computed
    read: target
    write: (value) ->
      if value.length > 0
        target value
        target.lastInvalid false
      else
        target.lastInvalid true
  target


并且您尝试从基础值而不是从可观察对象本身访问其他属性。所以你需要写:

person.name()
person.name.lastInvalid()
person.name.attempt()


演示JSFiddle

10-07 17:25