下面笔者用一个例子来展示用户控件的代码、使用和强大功能。在12. 如何在XPages中实现搜索视图里介绍的搜索视图的方法如果在每个需要搜索功能的页面上都做一遍,未免麻烦,也不易维护。于是,按照XPages提倡的做法,笔者将视图全文搜索的功能包含在一个SearchView用户控件里。打开数据库的全文检索,将这个控件放在任何含有标准视图控件的页面上,一个由一个输入框和搜索、清除两个按钮组成的具备下列功能的搜索条就准备就绪了。下面的代码片段包含一个SearchView用户控件和一个视图标准控件。
<xc:SearchView viewPanel="viewPanel1"></xc:SearchView>
<xp:viewPanel rows="15" id="viewPanel1"
viewStyle="width:100%" pageName="/record.xsp">
<xp:this.data>
<xp:dominoView var="view1" viewName="vwRecord"
expandLevel="1">
</xp:dominoView>
</xp:this.data>
<xp:this.facets>
<xp:pager partialRefresh="true" xp:key="headerPager"
id="pager1" layout="First Previous Group Next Last">
</xp:pager>
</xp:this.facets>
<xp:viewColumn id="viewColumn8" columnName="$8">
<xp:this.facets>
<xp:viewColumnHeader xp:key="header"
id="viewColumnHeader8" value="Date">
</xp:viewColumnHeader>
</xp:this.facets>
</xp:viewColumn>
<xp:viewColumn columnName="AccessTime" id="viewColumn1">
<xp:this.converter>
<xp:convertDateTime type="time"></xp:convertDateTime>
</xp:this.converter>
<xp:viewColumnHeader value="Access Time"
id="viewColumnHeader1">
</xp:viewColumnHeader>
</xp:viewColumn>
<xp:viewColumn columnName="StaffName" id="viewColumn4">
<xp:viewColumnHeader value="Staff Name"
id="viewColumnHeader4">
</xp:viewColumnHeader>
</xp:viewColumn>
<xp:viewColumn columnName="Department" id="viewColumn5">
<xp:viewColumnHeader value="Department"
id="viewColumnHeader5">
</xp:viewColumnHeader>
</xp:viewColumn>
<xp:viewColumn columnName="Office" id="viewColumn7">
<xp:viewColumnHeader value="Office"
id="viewColumnHeader7">
</xp:viewColumnHeader>
</xp:viewColumn>
</xp:viewPanel>
运行结果如下面两图:
控件的功能包括:
1. 在文本框中输入要搜索的词,按回车键或搜索按钮,关联的视图将显示全文检索后包含输入的词的文档。
2. 按清除按钮,输入框被清空,视图恢复原始显示。
唯一要注意的是需要搜索的视图控件的数据源需要当场定义,而不能选择页面内已经定义好的数据源。即在源代码中,viewPanel的data属性被设置:
<xp:this.data><xp:dominoView var="view1" viewName="vwRecord"></xp:dominoView></xp:this.data>
而不是value属性被设置:
value="#{view2}"
这样搜索的代码才能获得这个数据源。
控件源代码:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.afterRestoreView><![CDATA[#{javascript:function search(){var filter=getComponent("txtSearch").getValue();
var viewPanel1:com.ibm.xsp.component.xp.XspViewPanel = getComponent(compositeData.viewPanel);
var vd=viewPanel1.getData();
vd.setSearch(filter);}}]]></xp:this.afterRestoreView>
<xp:panel style="display:inline;">
<xp:inputText id="txtSearch">
<xp:eventHandler event="onkeypress" submit="true"
refreshMode="complete">
<xp:this.script><![CDATA[if (thisEvent.keyCode==13) {
return true;
}else{
return false;
}]]></xp:this.script>
<xp:this.action><![CDATA[#{javascript:search();}]]></xp:this.action>
</xp:eventHandler>
</xp:inputText>
<xp:button id="btnSearch" value="Search">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:
search();}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:button value="Clear" id="btnClear">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:getComponent("txtSearch").setValue("");
search();
}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:panel>
</xp:view>
为了方便部署,控件里的所有逻辑都用服务器端JavaScript(SSJS)写成,且包含在控件的同一文件内。代码有四个部分,分别是定义search()函数,txtSearch文本框的onkeypress事件响应程序,btnSearch和btnClear按钮的单击相应程序。值得注意的是,search()函数像浏览器中的JavaScript一样定义在页面内,而不是被包含在一个SSJS脚本库里。为了使这个函数在页面载入和以后每次响应事件后重新恢复的状态都有效,它被写在页面的afterRestoreView事件响应程序内。
包含控件自定义属性的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config>
<faces-config-extension>
<namespace-uri>http://www.ibm.com/xsp/custom</namespace-uri>
<default-prefix>xc</default-prefix>
</faces-config-extension>
<composite-component>
<component-type>SearchView</component-type>
<composite-name>SearchView</composite-name>
<composite-file>/SearchView.xsp</composite-file>
<composite-extension>
<designer-extension>
<in-palette>true</in-palette>
</designer-extension>
</composite-extension>
<property>
<property-name>viewPanel</property-name>
<property-class>string</property-class>
<display-name>viewPanel Id</display-name>
<property-extension>
<designer-extension>
<editor>com.ibm.xsp.extlib.designer.tooling.editor.XPageControlIDEditor</editor>
<default-value>viewPanel1</default-value>
</designer-extension>
</property-extension>
</property>
</composite-component>
</faces-config>