使用Ajax vor验证的dojo中的ValidationTextBox

使用Ajax vor验证的dojo中的ValidationTextBox,dojo,validation,Dojo,Validation,这是另一个我不敢相信还没有解决的问题。。。 我正在创建一个注册表。现在。。。我需要做一些ajax异步验证。 这就是我现在正在做的(请参阅底部的代码) 这很好,它可以缓存已经检查过的值,它是异步的,等等。但是: 在提交之前,您永远无法确定它是否经过验证。这 这是一个很大的问题,因为我还检查服务器端的东西。但是 还是。。。使此代码在提交时“强制”验证 把它变成一个真正的怪物 似乎每件事都应该做的事情都需要做很多工作 准备出发 (可能与2有关)我想不出一个方法来让这实际上是通用的。我还有10个字段需要

这是另一个我不敢相信还没有解决的问题。。。 我正在创建一个注册表。现在。。。我需要做一些ajax异步验证。 这就是我现在正在做的(请参阅底部的代码)

这很好,它可以缓存已经检查过的值,它是异步的,等等。但是:

  • 在提交之前,您永远无法确定它是否经过验证。这 这是一个很大的问题,因为我还检查服务器端的东西。但是 还是。。。使此代码在提交时“强制”验证 把它变成一个真正的怪物

  • 似乎每件事都应该做的事情都需要做很多工作 准备出发

  • (可能与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",
    
    });
    
    }
     );
    

    将自己从文本框本身中抽象出来,并在Submit上自定义表单。formDom.submit()之前使用的常规回调只调用formDijit.validate(),并将该布尔值传递给form.submit(如果为false,当然不会进行提交)

    换句话说,它期望验证器以阻塞/原子方式运行,并且在每个验证器函数解析返回值之前不会返回

    在您的情况下,
    dojo.Deferred
    很方便。发现自己在form.onSubmit期间从ajax请求中获取响应——一旦所有“正在进行的”ajax调用都解决了,那么如果真的是fire提交

    <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>
    
    
    声明('app.ValidationWorkspace',[ValidationTextBox]{
    invalidMessageLocal:'JS使您的条目无效',
    invalidMessageServer:'服务器要求与您输入的不同',
    无效消息:“”,
    regExp:'Foo*',//如果不以“Foo”开头,则验证false
    dfdValidator:未定义,
    验证器:函数(){
    var curVal=this.get(“值”);
    if(newregexp(this.RegExp.test(curVal)){
    //客户端传递,运行服务器端
    this.dfdValidator=dojo.xhrGet({
    url:'validate.sapi'+
    “?字段=”+this.inputNode.name+
    “&value=”+value
    });
    //我们不能在这里真正建立任何形式上的基础,但我们可能需要
    //设置消息(并显示,不显示)
    this.dfdValidator.then(dojo.hitch)(this,function(response){
    this.invalidMessage=this.invalidMessageServer+“:”+响应;
    }));
    }
    }
    });
    
    并用类似的方法对提交的表单进行变异:

    <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>
    
    
    dojo.addOnLoad(函数(){
    dijit.byId('form')。onSubmit=function(){
    var立即=真;
    风险值递延=[];
    dojo.some(dijit.byId('form')。_getDegenantFormWidgets(),函数(w){
    如果(w.validate){
    var tmp=w.validate();
    如果(!tmp)immediate=false;
    else{//检查它是否正在运行servervalidation
    if(w.dfdValidator){
    //是的,把它储存起来,这样我们就可以清点一下
    //在一切都过去之前不要屈服
    延迟推送(w.dfdValidator);
    }
    }
    }
    返回tmp;/*如果为false-一个字段失败-foreach(某些)停止循环*/
    });//结束道场
    var form=this.domNode
    var submit=function(){
    //在这里提交您的值的逻辑
    store.put(dojo.formToJson(form));
    }
    //如果本地验证程序失败,只需在此停止
    如果(立即==假){
    返回false;
    }否则,如果(延迟。长度>0){
    //在一切完成之前不要行动
    var dfdCounter=new dojo.Deferred();
    DFD计数器。然后(提交);
    var dfdCount=延迟的长度;
    var incrCount=0;
    var delayed=true;//延迟验证
    forEach(延迟,函数(serverValidatedComplete){
    serverValidatedComplete.then(函数(serverresponse){
    incrCount++;
    if(/REGEXPTOTESTRESPONSEFALSE/.test(serverresponse))
    延迟=错误;
    if(dfdCount==incrCount&&delayed==true)
    {/*是的,全部完成,有错误吗*/
    解析(/*此处为可选参数*/);
    }
    });
    });
    }否则{
    //没有运行服务器验证程序,本地验证成功
    提交();
    }
    //永远不要返回true,否则将按照HTML应该做的那样提交
    返回false;
    }//末端突变
    });
    
    公认的答案可能是正确的解决方案。 但是,对于非阻塞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;
      }
    
    });
      }
    );
    
    然后在文本框(或任何字段)的validate函数中,只需添加最小值即可:

        return this.ajaxValidate(value, {
           ajaxInvalidMessage: "Workspace taken",
           ajaxStore: g.stores.workspacesAnon,
           ajaxFilterField: 'name',
        });
    
    就这样。。。很好很清晰,你可以把它应用到你喜欢的任何领域。 (如果我收到足够多关于我的方法的鼓舞人心的评论,我会将此作为“接受的”答案…)


    Merc.

    应该将这两个功能划分为两个不同的功能流,我想,但请尝试一下:)虽然我没有运行实际的代码,但您会理解这个想法。。如果您希望在命令中显示invalidMessage,则可能会出现问题-此