这是另一个我不能相信尚未解决的问题...... 我正在创建一个注册表。现在......我需要做一些ajax异步验证。 这就是我现在正在做的事情(参见底部的代码)。
很好,它缓存已经检查过的值,它是异步等等但是:
您绝不会10000%确定在提交前已经过验证。这个 这是一个很大的交易,因为我也检查服务器端的东西。但 仍然......使这段代码在提交时“强制”验证 把它变成一个真正的怪物!
对于应有的事情,似乎需要做很多工作 准备好了
(可能与2有关)我想不出一种方法可以使它实际上是通用的。我有另外10个字段需要类似的验证,但所有验证都有所不同,除了Ajax调用...而且我没有剪切和粘贴此代码10次!
我错过了一些非常明显的东西吗?有什么想法吗?
define([
'dojo/_base/declare',
'dijit/form/ValidationTextBox',
'dojo/_base/lang',
'app/globals',
], function(
declare
, ValidationTextBox
, lang
, g
){
return declare('app.ValidationWorkspace', [ ValidationTextBox ], {
ajaxSaidNo: {},
ajaxSaidYes: {},
ajaxRequested: {},
onChange: function(value){
this.validate();
},
validator: function(value){
// console.log("Started validation for " + value);
// Ajax has already said no -- returning false straight away
if(this.ajaxSaidNo[value] ){
this.invalidMessage = 'Workspace taken';
return false;
}
// Run the normal field validators -- if they fail,
// return false
var validation = Validators.workspace(value);
if( ! validation.result){
this.invalidMessage = validation.message;
return false;
// At this point, regexp validators passed and Ajax hasn't said "no".
} else {
// console.log("OK, ajasSaidYes for " + value + " is " + this.ajaxSaidYes[value]);
if(! this.ajaxSaidYes[value] ){
g.stores.workspacesAnon.query({name: value}).then(
lang.hitch(this, function(res){
if(res && res.length ){
this.ajaxSaidNo[value] = true;
//console.log("Added to Ajaxfailed: " + value);
this.validate();
} else {
//console.log("Added to Ajaxsuccess: " + value);
this.ajaxSaidYes[value] = true;
this.validate();
}
})
);
}
return true;
}
},
invalidMessage: "Workspace name not valid",
missingMessage: "Workspace name cannot be empty",
});
}
);
答案 0 :(得分:1)
从TextBox本身提取自己并自定义onSubmit形式。在formDom.submit()之前使用的一般回调只是调用formDijit.validate()并将该布尔值传递给form.submit(如果它的错误,当然没有提交)。
换句话说,它期望验证器在每个验证器函数解析返回值之前运行阻塞/原子并且不返回。
在您的情况下,dojo.Deferred
会派上用场。发现自己在form.onSubmit期间从ajax请求中获取响应 - 并且一旦所有具有“正在进行中”的ajax调用已经解决,那么如果真的提交了火灾。
<div tada-dojo-type="dijit.form.Form" id="form">
<div data-dojo-type="app.ValidationWorkspace" name="inputfield" id="inputfield1"></div>
</div>
作为填写我在代码库中看不到的缺失内容的示例,下面是这个简化
<script>
declare('app.ValidationWorkspace', [ ValidationTextBox ], {
invalidMessageLocal : 'JS renders your entry invalid',
invalidMessageServer: 'Server expects something different then you entered',
invalidMessage: '',
regExp: 'Foo*', // validates false if does not start with "Foo"
dfdValidator: undefined,
validator: function() {
var curVal = this.get("value");
if(new RegExp(this.regExp).test(curVal)) {
// client-side passes, run serverside
this.dfdValidator = dojo.xhrGet({
url: 'validate.sapi'+
'?field=' + this.inputNode.name +
'&value='+ value
});
// we cannot truly base anything form-wise here, but we might want
// to set a message (and show it, left out)
this.dfdValidator.then(dojo.hitch(this, function(response) {
this.invalidMessage = this.invalidMessageServer + " : " + response;
}));
}
}
});
</script>
并使用与此类似的内容改变onSubmit上的表单:
<script>
dojo.addOnLoad(function() {
dijit.byId('form').onSubmit = function() {
var immediate = true;
var deferreds = [];
dojo.some(dijit.byId('form')._getDescendantFormWidgets(), function(w) {
if(w.validate) {
var tmp = w.validate();
if(!tmp) immediate = false;
else { // check if it has servervalidation in flight
if(w.dfdValidator) {
// it does, store it so we can keep a count and
// not submit before all has passed
deferreds.push(w.dfdValidator);
}
}
}
return tmp; /* if false - one field failed - foreach(some) stops loop */
}); // end dojo.some
var form = this.domNode
var submit = function() {
// logic to submit your values here
store.put(dojo.formToJson(form));
}
// simply stop here if local validators fail
if(immediate == false) {
return false;
} else if(deferreds.length > 0) {
// do not act before all is done
var dfdCounter = new dojo.Deferred();
dfdCounter.then(submit);
var dfdCount = deferreds.length;
var incrCount = 0;
var delayed = true; // delayed validation
dojo.forEach(deferred, function(serverValidatedComplete) {
serverValidatedComplete.then(function(serverresponse) {
incrCount++;
if(/REGEXPTOTESTRESPONSEFALSE/.test(serverresponse))
delayed = false;
if(dfdCount == incrCount && delayed == true)
{ /* YES, all is done, any errors? */
dfdCounter.resolve(/* optional arguments here */);
}
});
});
} else {
// no server validators are running, local validation succeeds
submit();
}
// never return true - or <form> will submit as HTML should be doing
return false;
} // end mutation
});
</script>
答案 1 :(得分:0)
接受的答案可能是正确的解决方案。 但是,对于非阻塞的ajax检查,我最终编写了一个简单的mixin:
define([
'dojo/_base/declare',
'dojo/_base/lang',
'app/globals',
], function(
declare
,lang
, g
){
return declare(null, {
ajaxSaidNo: {},
ajaxSaidYes: {},
ajaxRequested: {},
constructor: function(){
// Declaring object variable in constructor to make sure that
// they are not class-wide (since they will be in the prototype)
this.ajaxSaidNo = {};
this.ajaxSaidYes = {};
this.ajaxRequested = {};
},
// Overloads the validator, adding extra stuff
ajaxValidate: function(value, options){
// Set some defaults
options.ajaxInvalidMessage = options.ajaxInvalidMessage || "Value not allowed";
options.ajaxStore = options.ajaxStore || null;
options.ajaxFilterField = options.ajaxFilterField || 'name';
// No ajaxStore query available, return true
if( ! options.ajaxStore ){
return true;
}
// console.log("Started validation for " + value);
// Ajax has already said no -- returning false straight away
if(this.ajaxSaidNo[value] ){
this.invalidMessage = options.ajaxInvalidMessage;
return false;
}
// console.log("OK, ajasSaidYes for " + value + " is " + this.ajaxSaidYes[value]);
if(! this.ajaxSaidYes[value] ){
var filterObject = {};
filterObject[options.ajaxFilterField] = value;
options.ajaxStore.query( filterObject ).then(
lang.hitch(this, function(res){
if(res && res.length ){
this.ajaxSaidNo[value] = true;
//console.log("Added to Ajaxfailed: " + value);
this.validate();
} else {
//console.log("Added to Ajaxsuccess: " + value);
this.ajaxSaidYes[value] = true;
this.validate();
}
})
);
}
return true;
}
});
}
);
然后在文本框的验证功能(或任何字段,真的)中,只需添加最小值以使其工作:
return this.ajaxValidate(value, {
ajaxInvalidMessage: "Workspace taken",
ajaxStore: g.stores.workspacesAnon,
ajaxFilterField: 'name',
});
就是这样......好看又清晰,你可以把它应用到你喜欢的任何领域。 (如果我对我的方法收到足够令人鼓舞的评论,我会把这个作为“接受的”答案......)
Merc的。