【SAPUI5】SAPUI5中表单/字段校验的“最佳方案”

不可否认,对于页面上的输入框以及表单进行约束校验(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,谢谢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,924评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,902评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,716评论 0 239
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,783评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,166评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,510评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,784评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,476评论 0 196
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,196评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,459评论 2 243
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,978评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,321评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,964评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,046评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,803评论 0 193
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,530评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,420评论 2 265

推荐阅读更多精彩内容