我正在使用带有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");
}
}
});
答案 0 :(得分:4)
Backbone.Validation遗憾地不支持异步验证功能。这基本上是对默认主干验证流程的限制。它的设计只考虑了同步验证方式。
你基本上有两个选择:
我个人会选择2,因为同步ajax调用将锁定浏览器,直到调用完成。
更新备注:
在我回答这个问题之后,我做了快速谷歌搜索,看起来有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/,但与此无关。希望这可以帮助最终尝试异步验证的任何人。