不可否认,对于页面上的输入框以及表单进行约束校验(Constraint Validation)在前端开发当中可谓相当重要。在SAPUI5框架下实现约束校验的方法有很多,这里我们将讨论可能的实现方法以及“最佳方案”。之所以加引号是因为目前这只是我个人所发现的Best Practise。日后若有新发现我也会来随时更博,希望有朝一日能够去掉这个引号吧。
这里我们将校验大体分为两类,分别给它们起名字叫实时校验(Real-time Validation)和按需校验(On-demand Validation)。实时校验即随着用户的输入进行实时的校验并即刻给出反馈(如Error Message);相对于前者,按需校验则是在用户期望校验的时候对于一个或多个输入框进行统一校验。下面我们将逐个讨论他们的“最佳方案”。
文中部分代码出自openui5源码。
实时校验
1. 在change事件发生时校验
刚刚接触UI5校验这一块的时候,我的第一反应是在输入框相应change事件的时候做校验处理。
onChange : function(oEvent) {
// Validation code goes here.
}
这样做的确简单粗暴,但是当需要校验的输入框较多时则需要针对每个它们分别写逻辑。
优点: 简单粗暴
缺点: 不够只能,输入框增多时变得麻烦
适用于:页面上需要校验的输入框很少的情况
2. 在Message Manager中注册整个View
在UI5的官方教程中有一篇文章专门提到了使用Message Manager来进行输入框校验。结合在输入框中value的type或constraints属性使用起来非常酸爽,校验的问题分分钟搞定,代码看起来也简洁了不少。一句sap.ui.getCore().getMessageManager().registerObject(oView, true);
更是能将整个页面上的输入框通通甩给Message Manager去校验,自己当甩手掌柜,连出错信息都帮你做成i18n的,这简直就是Perfect Solution啊。
但是!方便之余仔细想来,Message Manager是不是帮我们做的有点过多了?我们看一下MessageManager.js关于出错信息的源代码:
var oMessage = new Message({
type: sap.ui.core.MessageType.Error,
message: oEvent.getParameter("message"),
target: sTarget,
processor: this.oControlMessageProcessor,
technical: bTechnical,
references: oReference,
validation: true
});
发现了吗,Message Manager也只是简单机械的从oEvent中拿翻译好的message加进来,然后抛给用户。对于一个generic的方法你已不能要求更多!那么问题来了,如果用户需要自己定制抛给用户的出错信息呢?比如下图:
作为一个End User看到这样一个出错信息,他的内心一定是。。。
其实我们想抛给用户的无非就是一个“请输入一个合法的Email地址”。但是Message Manager却无法帮我们做的。
优点:Super Easy
缺点:无法对Message进行定制化
适用于:如果你对UI5提供的Error Message都ok的话,完美
3. 【“最佳方案”】自己写异常处理方法
回过头来我们重新看Message Manager中的registerObject方法:
/**
* Register ManagedObject: Validation and Parse errors are handled by the MessageManager for this object
*
* @param {sap.ui.base.ManagedObject} oObject The sap.ui.base.ManagedObject
* @param {boolean} bHandleValidation Handle validation for this object. If set to true validation/parse events creates Messages and cancel event.
* If set to false only the event will be canceled, but no messages will be created
* @public
*/
MessageManager.prototype.registerObject = function(oObject, bHandleValidation) {
if (!oObject instanceof ManagedObject) {
jQuery.sap.log.error(this + " : " + oObject.toString() + " is not an instance of sap.ui.base.ManagedObject");
return;
}
oObject.attachValidationSuccess(bHandleValidation, this._handleSuccess, this);
oObject.attachValidationError(bHandleValidation, this._handleError, this);
oObject.attachParseError(bHandleValidation, this._handleError, this);
oObject.attachFormatError(bHandleValidation, this._handleError, this);
};
其实只是做了一件事情,就是将一些现成通用的异常处理方法attach到不同的事件上。那我们是不是也可以用类似的方法来attach我们自己的异常处理方法呢?
首先我们写一个方法,里面就做三件事情:1. 将出错的输入框标红;2. 抛给用户一条“人能看懂”的消息:“Please enter a valid Email address.”;3. 重新focus回这个输入框,让用户重新输入:
_handleError : function(oEvent) {
oEvent.getParameter('element').setValueState('Error');
oEvent.getParameter('element').setValueStateText('Please enter a valid Email address.');
oEvent.getParameter('element').focus();
}
然后我们在onInit方法里把这个方法attach给ValidationError事件:
this.getView().attachValidationError(this._handleError);
出错处理做好了,如果用户把输入改正确了,我们也要把输入框的状态更改回来,所以我们先写一个_handleSuccess方法:
_handleSuccess : function(oEvent) {
oEvent.getParameter('element').setValueState('None');
}
同样的,我们把这个方法attach给ValidationSuccess事件:
this.getView().attachValidationSuccess(this._handleSuccess);
来试一下效果:
优点:简洁,可控性强
缺点:暂未发现
适用于:当你对Message Manager不够满意,需要定制化的时候
按需校验
按需校验虽然不如实时校验出现的频率高,但是它在UI的开发中也非常重要。比如在提交表单之前,我们希望对整张页面上所有的用户输入进行校验,同时将非法输入全部标红。很遗憾如此重要的功能在UI5框架本身并未提供什么很好的解决方案,所以我们只能自己去写。
1. Loop所有需要校验的输入框
这可能就是最直观能够想到的方法了吧,这里就不放代码了。。。总之就是遍历校验所有需要校验的控件。
优点:直观,还有什么优点我再想想。。。
缺点:比较笨拙,后期增删控件的同时要记得维护这个遍历方法,不够通用
适用于:需要校验的输入框不多,未来UI改动不大的工程
2. 【“最佳方案”】Generic UI5 Form Validator
大写个出处先:
作者:Robin van het Hof
原博:https://blogs.sap.com/2015/11/01/generic-sapui5-form-validator/
源码:https://github.com/qualiture/ui5-validator
其实吧,Generic UI5 form validator所做的事情跟上一种方法差不多,就是遍历所有的控件。但是人家好用就好用在人家把逻辑抽出来做一个generic的工具啊。把Validator.js文件拷贝到项目当中,想用的时候非常简单:
this.validator = new Validator();
var isValid = this.validator.validate(this.byId('page_editor')
就这么两句话,就把整个page_editor中所有的控件遍历地验证了一遍,并且该标红的标红,最后返回整个页面是否通过验证。
在Validator.js文件中对于错误信息的处理也只是交给了Message Manager,如需抛定制化的错误信息,只要在_validate方法中catch代码块处做判断和替换即可。把这样一个通用的工具拷贝到项目当中,即可对项目当中所有的页面进行按需校验,非常方便。
优点:通用性,易用性兼备,可自己进行定制化修改
缺点:暂未发现
适用于:几乎所有的按需校验
总结
无论是时时校验还是按需校验,简便通用又能进行局部定制化都是最佳方案所应该具备的特征。如果你有更优解决方案也请留言或者邮件联系我:cong.wang@sap.com,谢谢!