68. XPages里的动态非空校验

在67. 表单提交与校验里,笔者提到在一个表单提交的数据就绪给业务逻辑使用前,通常会经过转换和验证的过程,在用XPages开发时也不例外。当一个编辑框的value属性被绑定到一个DominoDocument数据源的某个字段时,Domino Designer会自动根据该字段在表单上定义的数据类型为这个编辑框添加合适的转换器(converter),比如日期类型的会被添加xp:convertDateTime,数字类型的会被添加xp:convertNumber。同时,Designer还会自动在属性视图(properties window)的校验标签页显示恰当的校验选项。除了通用的非空校验外,对文本类型的编辑框会显示文本长度校验选项,对数字和日期类型的编辑框显示对应类型的取值范围的校验选项。这些图形化操作的背后,是XPages提供的丰富的校验器(validator),在属性视图的所有属性标签页的validators属性可以添加多个这些校验器。68. XPages里的动态非空校验_第1张图片

对这些校验器的功能和用法,IBM Notes and Domino Application Development wiki上有专文介绍Validation On An XPage。这些校验器用来实现特定的校验很方便,customValidator和validateExpression都可以用来添加自定义的校验逻辑。当这一切都不敷使用的时候,还能像在JSF里一样,添加以Java写的校验器。编写和在faces-config.xml里的配置与JSF里没有差别,最后选用xp:validator连接上。有兴趣的朋友可以参看JSF的相关资料。

笔者在这篇文章里主要介绍的是另一种情况下的校验。上面列举的各种校验都是在开发时已知目标栏位是哪些,对每一个提交数据的XPage都要在页面上为这些栏位逐一设置,我们不妨称之为静态校验。一个更方便的做法是在代码里集中校验,这样做校验的逻辑与界面代码分离,而且可以使程序运行时再获取要校验的栏位——同样不妨称之为动态校验——变为可能。动态校验有什么用处呢?试想在参数文档里配置和读取要校验的栏位,这样对于不同的表单就只需修改参数文档,而调用相同的代码进行校验。这样一个可配置的通用的校验“模块”可以作为一个部分整合进一个更大的可配置的流程引擎。笔者在Lotus Notes客户端和XPages的流程引擎里都是采用这样的方式。19. Notes客户机中的校验一文里介绍的用于非空校验的LotusScript类就被用来在客户端系统里进行动态校验。将这个类移植到XPages,用Java编写,就变成如下的代码。代码中的com.acme.tools.JSFUtil取自Karsten Lehmann的文章Helper classes to access the JSF environment and Lotus Notes data其中包含了获取JSF环境的诸如绑定值和视图上的组件的一些工具方法。

package starrow.xsp;

import java.util.Enumeration;
import java.util.Hashtable;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import com.acme.tools.JSFUtil;

public class Validator {
	public String hint=" is required.";
	Hashtable<String, String> fields;
	
	public Validator(){
		this.fields=new Hashtable<String, String>();
	}
	
	/**
	 * @param fieldName
	 * @param label
	 * Add a field to be checked.
	 */
	public void add(String fieldName, String label){
		fields.put(fieldName, label);
	}
	
	/**
	 * @param fieldName
	 * Add a field which has the same label with the name.
	 */
	public void add(String fieldName){
		add(fieldName, fieldName);
	}
	
	/**
	 * Return false on the first empty field.
	 */
	public boolean validate(){
		FacesContext context=FacesContext.getCurrentInstance();
		Enumeration<String> keys=fields.keys();
		String key;
		String msg;
		FacesMessage fm;
		UIInput input;
		while (keys.hasMoreElements()){
			key=keys.nextElement();
			input=(UIInput)JSFUtil.findComponent(key);
			if (input.getValue().equals("")){
				msg=fields.get(key) + hint;
				fm = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
				context.addMessage(input.getClientId(context), fm);
				input.setValid(false);
				return false;
			}
		}
		return true;
	}
	
	/**
	 * Validate all the fields. Return false if any field is empty.
	 */
	public boolean validateAll(){
		boolean result=true;
		FacesContext context=FacesContext.getCurrentInstance();
		Enumeration<String> keys=fields.keys();
		String key;
		String msg;
		FacesMessage fm;
		UIInput input;
		while (keys.hasMoreElements()){
			key=keys.nextElement();
			input=(UIInput)JSFUtil.findComponent(key);
			if (input.getValue()==null || input.getValue().equals("")){
				msg=fields.get(key) + hint;
				fm = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
				context.addMessage(input.getClientId(context), fm);
				input.setValid(false);
				result=false;
			}
		}
		return result;
	}
}
应用这个类时,要在需校验的XPage上放置一个Display Errors控件,也就是一个xp:messages。然后在提交表单的按钮里调用Validator实例的add方法添加要校验的栏位的名称和标签(界面上的栏位标题),并调用validateAll方法校验所有的添加的栏位。下面是一个校验方法里的代码片段,fields和labels是两个Vector<String>,分别装有从配置文档读取的需校验的栏位的名称和标签。
		Validator v=new Validator();
		for (int j=0; j<fields.size(); j++){
			v.add(fields.get(j), labels.get(j));
		}
		return v.validateAll();		
校验失败的显示效果可参考下图:

68. XPages里的动态非空校验_第2张图片 

你可能感兴趣的:(表单,校验,Lotus,notes,Xpages)