ExtJS的Valid事件调试

最近用extjs写点东西,出现了一个问题。背景是这样的,对于一个表单,里面有3个输入框,1个名称,1个描述,1个是Cron表达式。

要处理的结果是对于名称和描述,只要满足基本的要求(如最大、最小数目)就可以,但是对于Cron表达式,满足基本的要求之后,还要判断是否是Cron表达式,这是在后台的Java里面实现的,要引用import org.quartz.CronExpression,前台的调用则是通过DWR方式,而这样表单的下面有一个“确定”按钮,“确定”按钮在满足3个输入框都合法的情况下才可用。

刚开始的代码是这样的

var bakTimeTf = new Ext.form.TextField({ id : 'cronExp', fieldLabel : '备份时间', allowBlank : false, blankText :'不允许为空!' , minLength : 11, maxLength : 50, anchor : '95%', maxLengthText : '备份时间设置长度不超过50个字符', value : '0 0 12 * * ?', validator : function() { var onCheckCronExpres = function(isCronExpres) { if (!isCronExpres) { Ext.getCmp('bakStrategyComBtn').setDisabled(true); } else { Ext.getCmp('bakStrategyComBtn').setDisabled(false); } } var newValue = bakTimeTf.getValue().trim(); var cronArray = newValue.split(" "); if (cronArray.length == 6 || cronArray.length == 7) { // 验证cron表达式 CheckService.isValidCronExpression(newValue,onCheckCronExpres); return true; } return "Cron表达式格式有误"; } });

但是这样会导致不断的调用后台方法,而且确定按钮会不断的闪动。咋一看,原因是什么呢?仔细排查,发现在这个组建的panel里面设置了monitorValid=true,并且“确定”按钮的formbind为True。monitorValid=true表示为通过不断触发一个事件,来监视有效值的状态(在客户端进行)。由于validator的验证是在基本的验证之后再验证的,所以每做一次基本验证,同时就会做一次validator验证。

“确定”按钮不断闪动的原因是,由于错误的Cron表达式也能通过基本的验证,所以

1.       formbind=true会将“确定”置成可用,

2.       而Cron表达式验证的结果又会将这个置成“不可用”,

3.       而monitorValid检测通过基本验证,formbind=true会再次将“确定”置成可用,

4.       validator的验证是在所有的验证结果之后再验证的,结果又是将其置为不可用。

好了,知道原因之后就修改吧。


将原来的validator删除

新注册一个blur事件,当输入框失去焦点的时候就进行验证。

bakTimeTf.on("blur", function(field){ var newValue = bakTimeTf.getValue().trim(); CheckService.isValidCronExpression(newValue, onCheckCronExpres); });

但是这样的话,又有新的问题,如果在正确的Cron表达式输入之后,加入新的输入,使之错误,这时直接点击“确定”,也就是不触发“blur”事件,这时就能把错误的Cron表达式保存进去,这是与背景不符合的。



想了一下,又进行了一次大改,把panel的monitorValid属性和“确定”按钮的formbind注释掉,自己来验证每个输入框是否valid。

 
Ext.getCmp("strategyName").on("valid", function() { isNameValid = true; // 当且仅当3个都有效 if (isCronValid && isDescValid) { Ext.getCmp('bakStrategyComBtn').setDisabled(false); } }); Ext.getCmp("strategyName").on("invalid", function() { isNameValid = false; if (Ext.getCmp('bakStrategyComBtn').disabled == false) { Ext.getCmp('bakStrategyComBtn').disable(); } }) Ext.getCmp("descripton").on("valid", function() { isDescValid = true; if (isCronValid && isNameValid) { Ext.getCmp('bakStrategyComBtn').setDisabled(false); } }) Ext.getCmp("descripton").on("invalid", function() { isDesValid = false; if (Ext.getCmp('bakStrategyComBtn').disabled == false) { Ext.getCmp('bakStrategyComBtn').disable(); } }) bakTimeTf.on("valid", function() { var newValue = bakTimeTf.getValue().trim(); CheckService.isValidCronExpression(newValue, onCheckCronExpres); }) bakTimeTf.on("invalid", function() { isCronValid = false; if (Ext.getCmp('bakStrategyComBtn').disabled == false) { Ext.getCmp('bakStrategyComBtn').disable(); } }) function onCheckCronExpres(isCronExpres) { //用于打印CronExpression是否合法 JsLog.log("------ " + isCronExpres); if (isCronExpres) { //验证Cron表达式是否合法。 bakTimeTf.clearInvalid(); isCronValid = true; if (isNameValid && isDescValid) { Ext.getCmp('bakStrategyComBtn').setDisabled(false); } } else { bakTimeTf.markInvalid(); if (Ext.getCmp('bakStrategyComBtn').disabled == false) { Ext.getCmp('bakStrategyComBtn').disable(); } } }
但是这样,还是不断的调用后来的java方法。问题又出在哪里呢?

通过加入Log.log语句,发现如果不调用CheckService.isValidCronExpression,则不会出现循环,CheckService.isValidCronExpression很简单,没有循环。而这说明

1.    valid触发只有一次

2.       CheckService.isValidCronExpression完成后的回调函数onCheckCronExpres可能有触发了valid事件,从而导致不断调用后台方法。

排查了一下,原因是在bakTimeTf.clearInvalid();,将这句注释掉之后,一切都正常工作了。

整个世界清净了。。。。。。。。。。

你可能感兴趣的:(java,function,DWR,ExtJs,import,cron)