用于backbone.js验证的自定义验证器

时间:2014-02-18 13:26:33

标签: javascript validation backbone.js playframework coffeescript

我正在使用带有backbone.validation plugin的Backbone.js来构建custom validator,以检查电子邮件地址(在表单输入中输入)是否已被占用。

新的验证器名为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"
...

这不起作用,我无法理解。我哪里错了?

编辑:代码转换为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");
    }
  }
});

2 个答案:

答案 0 :(得分:4)

Backbone.Validation遗憾地不支持异步验证功能。这基本上是对默认主干验证流程的限制。它的设计只考虑了同步验证方式。

你基本上有两个选择:

  • 为ajax调用指定async:false选项
  • 为此案例实施您自己的验证流程

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

更新备注:

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

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

答案 1 :(得分: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/,但与此无关。希望这可以帮助最终尝试异步验证的任何人。