1

我使用Backbone.js和backbone.validation plugin来构建custom validator,它检查是否已输入电子邮件地址(已输入表单输入)。backbone.js验证的自定义验证器

新的验证被称为emailAvailable,你可以看到如下: (注意:这是Coffescript,但在底部你会发现代码转换为标准的JavaScript)

# ================================== 
#   MODELS 
# ==================================  
User = Backbone.Model.extend(

    urlRoot: "/user" 

    validation: 
     email: 
      fn: "emailAvailable" 

    emailAvailable: (value, attr, computedState) -> 
     // Ajax call to server (Play framework 2.2.1): returns the string "email available" if it doesn't find the email and returns the email address if it find it 
     checkEmail = $.ajax(jsRoutes.controllers.Signup.isEmailExists(value)) 
     checkEmail.done (msg) -> 
     emailFound = msg 
     if value is emailFound 
      return "already taken" 

     return 
) 

# ================================== 
#   VIEWS 
# ==================================  
SignUpView = Backbone.View.extend(
    initialize: -> 
     Backbone.Validation.bind(this) 

    el: "body" 

    events: 
     "change  input"  : "validateInput" 

    validateInput: (event) -> 
     input = $(event.currentTarget) 
     inputName = event.currentTarget.name 
     inputValue = input.val() 

     this.model.set(inputName, inputValue) 
     if this.model.isValid(inputName) 
      input.removeClass "error" 
      input.addClass "valid" 
     else 
      input.removeClass "valid" 
      input.addClass "error" 
... 

这不起作用我不明白为什么。我错在哪里?

EDIT:代码转换为JavaScript的

var SignUpView, User; 

User = Backbone.Model.extend({ 
    urlRoot: "/user", 
    validation: { 
    email: { 
     fn: "emailAvailable" 
    } 
    }, 
    emailAvailable: function(value, attr, computedState) { 
    var checkEmail; 
    checkEmail = $.ajax(jsRoutes.controllers.Signup.isEmailExists(value)); 
    checkEmail.done(function(msg) { 
     var emailFound; 
     emailFound = msg; 
     if (value === emailFound) { 
     return "already taken"; 
     } 
    }); 
    } 
}); 

SignUpView = Backbone.View.extend({ 
    initialize: function() { 
    return Backbone.Validation.bind(this); 
    }, 
    el: "body", 
    events: { 
    "change  input": "validateInput" 
    }, 
    validateInput: function(event) { 
    var input, inputName, inputValue; 
    input = $(event.currentTarget); 
    inputName = event.currentTarget.name; 
    inputValue = input.val(); 
    this.model.set(inputName, inputValue); 
    if (this.model.isValid(inputName)) { 
     input.removeClass("error"); 
     return input.addClass("valid"); 
    } else { 
     input.removeClass("valid"); 
     return input.addClass("error"); 
    } 
    } 
}); 
+0

这不是JavaScript,请修复标签。 – jgillich

+0

看看编辑,我已将代码转换为javascript –

回答

4

Backbone.Validation可悲不支持异步验证函数。这基本上是默认骨干验证流程的限制。它的设计只考虑了同步验证方式。

你已经基本上2种选择:

  • 指定异步:对于AJAX调用
  • 假选项实施这种情况下自己的验证流程

我个人使用选项2去,因为同步ajax调用将锁定浏览器直到调用完成。

更新注:

我做了快速谷歌搜索后,我回答了这个问题,它看起来像有扩展Backbone.Validation,允许非同步的验证。请注意,我没有用过,也没有以任何方式测试了它:)

链接:https://github.com/suevalov/async.backbone.validation

+0

这个异步验证插件看起来很有前途,但如何配置骨干验证以使用它?文档只是链接到骨干验证。 – DagR

0

你将不得不自己做你的异步验证功能。这里是你如何做到这一点,没有任何插件,只是一个小逻辑和良好的旧编码。

1)让我们开始您的将保存模型的函数。您将需要一个Deferred对象,这样,节省发生之前:

this.asyncValidation = $.Deferred(); 

2)然后,你将不得不手动调用自定义的验证功能:

this.model.asyncValidate(); 

3)然后,你将不得不等到你的异步验证完成。一旦完成,只需保存你的模型:

$.when(this.checkDuplicatesFinished).done(function() { 

4)检查有自己的异步验证的结果你自己的模型属性:

if (self.model.asyncValidateOK) { 

5)保存模型:

self.model.save(); 

下面是代码共:

this.asyncValidation = $.Deferred(); 
this.model.asyncValidate(asyncValidation); 
var self = this; 

$.when(this.checkDuplicatesFinished).done(function() { 
    if (self.model.asyncValidateOK) { 
     self.model.save(); 
    } 
}); 

现在,让我们看看你的模型。这是新的客户验证功能将要定位的位置。它非常简单,你需要一个布尔变量来存储验证的结果和验证方法本身。

window.app.MyModel = Backbone.Model.extend({ 

    asyncValidateOK: true, 
    asyncValidate: function (defferedObject) { 
     var self = this; 
     var attrs = this.attributes; // a copy of the params that are automatically passed to the original validate method 
     $.get("someAsyncMethod", {}, function(result){ 

      // do your logic/validation with the results 
      // and tell the referred object you finished 
      if (true){ //validation ok (use your own logic) 

       self.asyncErrors = []; // no errors 
       self.asyncValidateOK = true; 
       deferredObject.resolve(); 

      } else { // validation not ok 

       self.asyncErrors.push(); 
       self.asyncValidateOK = false; 
       deferredObject.resolve(); 

      } 
     }); 
    } 
}); 

更多文档检查http://backbonejs.org/,但没有什么与此相关的。希望这有助于任何最终尝试异步验证的人。