本文的目的与上一篇文章相同 - 涵盖 RichFaces 中经常在 RichFaces 用户论坛 上提出的一些特定组件问题。一些观点(也许所有观点)你可能已经知道... 但不要忘记,每个人有时都是从零开始的 :) 因此,我的目的是通过一些类似这样的启动样本来帮助刚开始使用 RichFaces 的朋友们。

在这里,我将创建一个简单的搜索/结果表单。让我们假设每个搜索结果对象都包含大量类似信息,应该完全显示。因此,我们将使用 标签式结果表示

从一开始,我们就创建了一个具有 RichFaces 支持的简单项目。我使用了 JSF 1.2、Facelets 1.1.14 和 RichFaces 3.3.1,并在 Tomcat 6 下部署。简单项目创建的过程在 RichFaces 开发者指南。第3节 中有详细描述。

如果你已经访问过我们的 richfaces-demo,你可能在许多示例中看到了简单的 首都 对象列表(建议框表格排序示例 等...)。因此,让我们重用现有 Java 代码。只需下载 资源,并将其放置在创建的项目中的一些源包中。然后在 faces-config 中注册 CapitalsBean

 <managed-bean>
  <managed-bean-name>capitalsBean</managed-bean-name>
  <managed-bean-class>org.richfaces.demo.capitals.CapitalsBean</managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>
 </managed-bean>

查看JavaBean代码。我们有一个包含所有首都的首都列表。我们需要添加一个额外的列表来存储满足搜索条件的首都。让我们称它为foundCapitals。同时,我们还需要添加一个属性来存储搜索条件。在这种情况下,我使用了简单搜索,通过首都名称使用startsWith方法。因此,接下来需要添加的代码如下:

private ArrayList<Capital> foundCapitals = new ArrayList<Capital>();
private String searchValue = "";

// Do not forget to add getters and setters

现在是时候为这种情况工作在页面源代码了。接下来的部分代表一个搜索面板

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:a4j="http://richfaces.org/a4j"
	xmlns:rich="http://richfaces.org/rich"
	xmlns:c="http://java.sun.com/jstl/core">
	<h:form>
		<rich:panel header="Simple Search">
			<h:outputText value="Enter the first letters of the capitals:" />

			<h:inputText id="searchField" value="#{capitalsBean.searchValue}"/>

			<rich:hotKey selector="##{rich:clientId('searchField')}" key="return" 
                            handler="#{rich:element('search')}.onclick();return false;"/>

			<a4j:commandButton action="#{capitalsBean.search}" value="Search" 
			    reRender="output" id="search"/>
		</rich:panel>
	</h:form>
</ui:composition>

在那里,我想引起你注意的组件是rich:hotKey。它实现了当用户在输入中按下Enter键时发送ajax请求的常见需求。#{rich:clientId}函数返回要附加热键的搜索输入的clientId。并且当在输入中按下Enter键后,将通过在handler属性中定义的JS(#{rich:element}通过其Id返回按钮DOM元素)来点击搜索按钮。

现在让我们定义应该使用foundCapitals列表动态创建的tabPanel

请在面板代码之后添加以下代码

<a4j:outputPanel id="output">
	<rich:tabPanel id="tapPanel" width="700" rendered="#{not empty capitalsBean.foundCapitals}">
		<c:forEach items="#{capitalsBean.foundCapitals}" var="cap">
			<rich:tab name="#{cap.name}" >
				<f:facet name="label">
				<h:panelGrid columns="2">
					<h:outputText value="#{cap.name}" />
					<h:graphicImage value="/images/icons/delete.gif" 
					    style="width:12px; height:12px;" 
					    onclick="myFunc('#{cap.name}'); Event.stop(event);"/>
				</h:panelGrid>
				</f:facet>
				<h:panelGrid columns="2" style="margin:20">
					<h:outputText value="State Name" />
					<h:inputText value="#{cap.state}" />
					<h:outputText value="State Capital" />
					<h:inputText value="#{cap.name}" />
					<h:outputText value="State TimeZone" />
					<h:inputText value="#{cap.timeZone}" />
				</h:panelGrid>
			</rich:tab>
		</c:forEach>
	</rich:tabPanel>
	<h:outputText value="No active search results." 
		style="font-style:italic" rendered="#{empty capitalsBean.foundCapitals}"/>
</a4j:outputPanel>
<a4j:jsFunction action="#{capitalsBean.remove}" name="myFunc"
	ajaxSingle="true" reRender="output">
	<a4j:actionparam name="current"/>
</a4j:jsFunction>

以下要点需要强调:我们将使用c:forEach来动态创建标签。这是RichFaces新手经常犯错的地方。你不能使用重复组件(既不是ui:repeat也不是a4j:repeat),因为它们在页面渲染时间工作,并且不会在JSF树中创建组件,只是迭代相同的实例。我们应该使用c:forEach标签,它在视图构建阶段工作,并导致实际标签组件被添加到JSF树中。有关更多详细信息,请参阅c:forEach与ui:repeat在Facelets中的比较文章。

c:forEach内部,我们定义了一个标签,其内容依赖于迭代变量的属性。每个标签将包含使用搜索找到的每个首都对象的信息。

标签面包含标签的文本标签和调用带当前标签名称参数的jsFunction的关闭控制。因此,a4j:jsFunction将在移除控制被点击后引发ajax请求,并将该标签的首都名称通过actionparam放入请求参数。

在标签移除和搜索之后,我们应该更新标签面板并渲染标签,如果找到对象或如果没有结果则显示某些标签。正如你所看到的,我们正在使用rendered属性在tabPanel和outputText组件上定义根据是否找到某些对象应该渲染什么。还有一个地方需要强调RichFaces的限制之一。我们不应该直接条件性地重新渲染条件性渲染的元素(outputText和tabPanel)。RichFaces的Ajax机制不允许插入任何内容。我们应该更新一些现有的DOM节点。a4j:outputPanel应该添加在条件性渲染元素周围,我们将更新这个outputPanel。

最后一步是实现我们的CapitalsBean中的搜索和移除方法。

public void search() {
	foundCapitals.clear();
	for (Capital currentCapital : capitals) 
		if (currentCapital.getName().startsWith(searchValue)) 
			foundCapitals.add(currentCapital);
}

public Capital getCapitalIdByName(String name) {
	for (Capital currentCapital : capitals) {
		if (currentCapital.getName().equals(name))
			return currentCapital;
	}
	return null;
}

public void remove() throws Exception {
	Capital currentCapital = getCapitalIdByName(FacesContext
			.getCurrentInstance().getExternalContext()
			.getRequestParameterMap().get("current"));
	if (null != currentCapital)
		foundCapitals.remove(currentCapital);
	else
		throw new Exception("capital name parameter is null");
}

现在让我们部署应用程序并启动服务器以查看结果。

没有找到结果

带有结果的标签面板

我希望在RichFaces使用中应该注意的一些细节,这些细节已经在我们的文档中呈现,并在本文中再次强调,将帮助开发者减少构建类似功能所需的时间。


返回顶部