多个动态包含一个JSF标签

每个JSF开发人员都知道ui:include和ui:param标签。 您可以包括一个facelet(XHTML文件)并传递一个对象,该对象将在包含的facelet中可用,如下所示:

<ui:include src="/sections/columns.xhtml"><ui:param name="columns" value="#{bean.columns}"/>
</ui:include>

因此,您可以在带有dynamich列的PrimeFaces DataTable中使用它(p:columns)

<p:dataTable value="#{bean.entries}" var="data" rowKey="#{data.id}" ...>...<ui:include src="/sections/columns.xhtml"><ui:param name="data" value="#{data}"/><ui:param name="columns" value="#{bean.columns}"/></ui:include></p:dataTable>

其中包含的facelet可能包含此代码

<ui:composition xmlns="http://www.w3.org/1999/xhtml"xmlns:p="http://primefaces.org/ui"xmlns:ui="http://java.sun.com/jsf/facelets"...><p:columns value="#{columns}" var="column"><f:facet name="header"><h:outputText value="#{msgs[column.header]}"/></f:facet>// place some input / select or complex composite component for multiple data types here.// a simple example for demonstration purpose:<p:inputText value="#{data[column.property]}"/></p:columns>
</ui:composition>

#{bean.columns}表示描述这些列的特殊对象的列表。 我将此类对象命名为ColumnModel。 所以,这是一个
列出<ColumnModel>。 ColumnModel具有例如属性标头和属性。

继续。 现在,如果要添加对排序/过滤的支持,我们可以使用动态路径,该路径引用包含排序或/和过滤功能的特定facelet文件。 简单地将src属性绑定到bean属性。

<ui:include src="#{bean.columnsIncludeSrc}"><ui:param name="data" value="#{data}"/><ui:param name="columns" value="#{bean.columns}"/>
</ui:include>

豆有类似的东西

private boolean isFilterRight;
private boolean isSortRight// setter / getterpublic String getColumnsIncludeSrc() {if (isFilterRight && isSortRight) {return "/include/columnsTableFilterSort.xhtml";} else if (isFilterRight && !isSortRight) {return "/include/columnsTableFilter.xhtml";} else if (!isFilterRight && isSortRight) {return "/include/columnsTableSort.xhtml";} else {return "/include/columnsTable.xhtml";}
}

根据所设置的布尔权限,包含了不同的方面。 因此,将要包含的文件的决定放在Bean中。 为了更加灵活,我们可以将表封装在一个复合组件中,并将决策逻辑移至组件类。

<cc:interface componentType="xxx.component.DataTable"><cc:attribute name="id" required="false" type="java.lang.String"shortDescription="Unique identifier of the component in a NamingContainer"/><cc:attribute name="entries" required="true"shortDescription="The data which are shown in the datatable. This is a list of object representing one row."/><cc:attribute name="columns" required="true" type="java.util.List"shortDescription="The columns which are shown in the datatable. This is a list of instances of type ColumnModel."/>...
</cc:interface>
<cc:implementation><p:dataTable value="#{cc.attrs.entries}" var="data" rowKey="#{data.id}" ...>...<ui:include src="#{cc.columnsIncludeSrc}"><ui:param name="data" value="#{data}"/><ui:param name="columns" value="#{cc.attrs.columns}"/></ui:include></p:dataTable>
</cc:implementation>

ui:include如何工作? 这是在构建视图时应用的标记处理程序。 在JSF 2中,组件树根据POST请求构建两次,一次在RESTORE_VIEW阶段,一次在RENDER_RESPONSE阶段。 在GET上,它在RENDER_RESPONSE阶段构建一次。 此行为在JSF 2规范中指定,并且在Mojarra和MyFaces中相同。 如果页面作者使用条件包含或条件模板,则必须在RENDER_RESPONSE中建立视图。 因此,您可以确保ui:include的src属性在呈现阶段之前不久就得到了评估。

但是到了重点! 到目前为止,我所写的内容只是介绍了扩展ui:include的动机。 最近,我有一项任务要使用带有动态列的ap:dataTable和p:rowEditor。 在PrimeFaces展示柜中就是这样的 。 问题只是–这种编辑功能不支持p:columns。 我的想法是动态地多次添加p:column标签,但是具有不同的上下文参数。 您可以将其想象为ui:include和ui:param在循环中。 在上面的示例中,我们打算遍历List <ColumnModel>。 每次循环迭代都应在所包含的facelet中提供ColumnModel类型的实例。 因此,我编写了一个自定义标签处理程序以多次包含任何facelet。

package xxx.taghandler;import xxx.util.VariableMapperWrapper;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.el.VariableMapper;
import javax.faces.component.UIComponent;
import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.TagAttribute;
import javax.faces.view.facelets.TagAttributeException;
import javax.faces.view.facelets.TagConfig;
import javax.faces.view.facelets.TagHandler;/*** Tag handler to include a facelet multiple times with different contextes (objects from "value").* The attribute "value" can be either of type java.util.List or array.* If the "value" is null, the tag handler works as a standard ui:include.*/
public class InlcudesTagHandler extends TagHandler {private final TagAttribute src;private final TagAttribute value;private final TagAttribute name;public InlcudesTagHandler(TagConfig config) {super(config);this.src = this.getRequiredAttribute("src");this.value = this.getAttribute("value");this.name = this.getAttribute("name");}@Overridepublic void apply(FaceletContext ctx, UIComponent parent) throws IOException {String path = this.src.getValue(ctx);if ((path == null) || (path.length() == 0)) {return;}// wrap the original mapper - this is important when some objects passed into include via ui:param// because ui:param invokes setVariable(...) on the set variable mappper instanceVariableMapper origVarMapper = ctx.getVariableMapper();ctx.setVariableMapper(new VariableMapperWrapper(origVarMapper));try {this.nextHandler.apply(ctx, null);ValueExpression ve = (this.value != null) ? this.value.getValueExpression(ctx, Object.class) : null;Object objValue = (ve != null) ? ve.getValue(ctx) : null;if (objValue == null) {// include facelet only oncectx.includeFacelet(parent, path);} else {int size = 0;if (objValue instanceof List) {size = ((List) objValue).size();} else if (objValue.getClass().isArray()) {size = ((Object[]) objValue).length;}final ExpressionFactory exprFactory = ctx.getFacesContext().getApplication().getExpressionFactory();final String strName = this.name.getValue(ctx);// generate unique Id as a valid Java identifier and use it as variable for the provided value expressionfinal String uniqueId = "a" + UUID.randomUUID().toString().replaceAll("-", "");ctx.getVariableMapper().setVariable(uniqueId, ve);// include facelet multiple timesStringBuilder sb = new StringBuilder();for (int i = 0; i < size; i++) {if ((strName != null) && (strName.length() != 0)) {// create a new value expression in the array notation and bind it to the variable "name"sb.append("#{");sb.append(uniqueId);sb.append("[");sb.append(i);sb.append("]}");ctx.getVariableMapper().setVariable(strName,exprFactory.createValueExpression(ctx, sb.toString(), Object.class));}// included facelet can access the created above value expressionctx.includeFacelet(parent, path);// reset for next iterationsb.setLength(0);}}} catch (IOException e) {throw new TagAttributeException(this.tag, this.src, "Invalid path : " + path);} finally {// restore original mapperctx.setVariableMapper(origVarMapper);}}
}

最重要的调用是ctx.includeFacelet(parent,path)。 JSF API中的 includeFacelet(…)方法在相对于当前标记的某个路径上包含了facelet标记。 类VariableMapperWrapper用于通过ui:param从名称到值的映射。 对于带有列的示例,在每次调用includeFacelet(...)之前,变量列还将映射到表达式#{columns [0]},#{columns [1]}等。 好吧,不完全是这些表达式,在列的位置应该是一个唯一的名称,该名称再次映射到columns对象(以避免可能的名称冲突)。 映射器类如下所示

package xxx.util;import java.util.HashMap;
import java.util.Map;
import javax.el.ELException;
import javax.el.ValueExpression;
import javax.el.VariableMapper;/*** Utility class for wrapping a VariableMapper. Modifications occur to the internal Map instance.* The resolving occurs first against the internal Map instance and then against the wrapped VariableMapper* if the Map doesn't contain the requested ValueExpression.*/
public class VariableMapperWrapper extends VariableMapper {private final VariableMapper wrapped;private Map<String, ValueExpression> vars;public VariableMapperWrapper(VariableMapper orig) {super();this.wrapped = orig;}@Overridepublic ValueExpression resolveVariable(String variable) {ValueExpression ve = null;try {if (this.vars != null) {// try to resolve against the internal mapve = this.vars.get(variable);}if (ve == null) {// look in the wrapped variable mapperreturn this.wrapped.resolveVariable(variable);}return ve;} catch (Throwable e) {throw new ELException("Could not resolve variable: " + variable, e);}}@Overridepublic ValueExpression setVariable(String variable, ValueExpression expression) {if (this.vars == null) {this.vars = new HashMap<String, ValueExpression>();}return this.vars.put(variable, expression);}
}

在taglib XML文件中注册标签处理程序,您就可以完成。

<tag><tag-name>includes</tag-name><handler-class>xxx.taghandler.InlcudesTagHandler</handler-class><attribute><description><![CDATA[The relative path to a XHTML file to be include one or multiple times.]]></description><name>src</name><required>true</required><type>java.lang.String</type></attribute><attribute><description><![CDATA[Objects which should be available in the included XHTML files. This attribute can be eitherof type java.util.List or array. If it is null, the tag handler works as a standard ui:include.]]></description><name>value</name><required>false</required><type>java.lang.Object</type></attribute><attribute><description><![CDATA[The name of the parameter which points to an object of each iteration over the given value.]]></description><name>name</name><required>false</required><type>java.lang.String</type></attribute>
</tag>

现在我可以在复合组件中使用它了

<p:dataTable value="#{cc.attrs.entries}" var="data" rowKey="#{data.id}" ...>...<custom:includes src="#{cc.columnsIncludeSrc}" value="#{cc.attrs.columns}" name="column"><ui:param name="data" value="#{data}"/></custom:includes> </p:dataTable>

典型的facelet文件(和组件树)包含一个非常规则的p:column标记,这意味着我们能够使用DataTable的所有功能!

<ui:composition xmlns="http://www.w3.org/1999/xhtml"xmlns:p="http://primefaces.org/ui"xmlns:ui="http://java.sun.com/jsf/facelets"...><p:column headerText="#{msgs[column.header]}"><p:cellEditor><f:facet name="output"><custom:typedOutput outputType="#{column.outputTypeName}"typedData="#{column.typedData}"value="#{data[column.property]}"timeZone="#{cc.timeZone}"calendarPattern="#{cc.calendarPattern}"       locale="#{cc.locale}"/></f:facet><f:facet name="input"><custom:typedInput inputType="#{column.inputTypeName}"typedData="#{column.typedData}"label="#{column.inputTypeName}"value="#{data[column.property]}"onchange="highlightEditedRow(this)"timeZone="#{cc.timeZone}"calendarPattern="#{cc.calendarPattern}"locale="#{cc.locale}"/></f:facet></p:cellEditor></p:column>
</ui:composition>

注意 :此方法可以应用于其他组件和用例。 InlcudesTagHandler可以正常运行。 例如,我可以想象在没有基础MenuModel的情况下在PrimeFaces中创建一个动态Menu组件。 当然,仍然需要某个模型类的列表或数组。

参考:在我们的软件开发博客上, JCG合作伙伴 Oleg Varaksin的一个JSF标签包含了多个动态 。

翻译自: https://www.javacodegeeks.com/2013/06/multiple-dynamic-includes-with-one-jsf-tag.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367726.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[JLOI2014]松鼠的新家

嘟嘟嘟 这还是一道树链剖分板子题呀&#xff01; 从1到n - 1枚举a[i]&#xff0c;每一次使节点a[i]到a[i 1]的路径加1&#xff0c;但这样的话除a[1]&#xff0c;每一个点都多加了一个1&#xff0c;所以输出答案的时候减1即可。 1 #include<cstdio>2 #include<iostrea…

CSS3-背景(background-image、background-size、background-origin、background-clip)

CSS3中新的背景属性&#xff1a;background-image、background-size、background-origin、background-clip 背景图片&#xff1a;background-image CSS3中可以通过background-image属性添加背景图片。 不同的背景图像和图像用逗号隔开&#xff0c;所有的图片中显示在最顶端的为…

使用String.intern()减少内存使用

时不时地会有一个垂死的生产应用程序。 而且您知道您需要尽快对其进行修补。 我们也一样&#xff0c;并认为分享最近的一个战争故事将很有趣。 在这种情况下&#xff0c;我们就有机会使用String.intern&#xff08;&#xff09;之类的简单补丁来修补应用程序。 但是&#xff0c…

CSS实现比翼双飞和圣杯布局模型效果

圣杯模型和比翼双飞模型主要的特指1.首先加载的是中间部分&#xff0c;其次是左边&#xff0c;然后是右边 2.中间是自适应&#xff0c;二边是定宽 实现方法1.grid2.margin float position:releative父亲加padding 挤进去3.margin float box-size:border-box 1.gridhtml:&l…

jmeter创建高级测试计划

如果应用程序使用重写地址而不是使用cookie存储信息&#xff0c;需要做一些额外的工作去测试程序 为了正确的响应重写地址&#xff0c;jmeter 需要解析 从服务器获取html 并且检索会话ID, 1 合理利用pre-processors-http url rewriting modifier 来完成&#xff0c;简单的输入s…

单元测试技巧:创建描述性测试

您的单元测试应尽可能具有描述性。 他们给您的反馈应该非常清楚&#xff0c;您甚至不需要启动调试器并一步一步地检查代码来检查局部变量。 为什么&#xff1f; 因为那需要时间&#xff0c;而且我们很懒&#xff0c;对吗&#xff1f; 为此&#xff0c;您需要创建描述性测试。 有…

vue.js--基础事件定义,获取数据,执行方法传值

<template><div id"app"> <h1>{{ msg }}</h1> <br> <button v-on:click"run1()"> 第一种写法</button> <br> <button clickrun2()> 第二种写法</button> <br> <button clickgetMsg(…

Spring集成–强大的拆分器聚合器

坚固是什么意思&#xff1f; 在本文的上下文中&#xff0c;健壮性是指在不立即返回到调用者的情况下管理流中的异常条件的能力。 在某些处理方案中&#xff0c; n个 m个回答足以做出结论。 通常具有这些趋势的示例处理场景是&#xff1a; 财务&#xff0c;保险和预订系统的…

填充一个池需要多少个线程?

近几个月来&#xff0c;我们一直看到一小部分但持续的操作失败&#xff0c;并带有一个奇怪的异常– org.springframework.jdbc.CannotGetJdbcConnectionException –“无法获得JDBC连接&#xff1b; 嵌套异常是java.sql.SQLException&#xff1a;客户端尝试检出Connection的尝试…

@font-face 用字体画图标

HTML 1 <body>2 <!-- ul.layout>li*5>a[href#]>i.icon -->3 <!-- Sublime Text 快捷拼写 -->4 <ul class"layout">5 <li><a href"#"><i class"icon">&#xe601;</…

java mapfile_基于文件的数据结构:关于MapFile

MapFile是已经排过序的SequenceFile&#xff0c;它有索引&#xff0c;所以可以按键查找1.MapFile的写操作MapFile的写操作类似于SequenceFile的写操作。新建一个MapFile.Writer实例&#xff0c;然后调用append()方法顺序写入文件内容。如果不按顺序写入&#xff0c;就抛出一个I…

java 循环依赖_解决Java循环依赖的问题

最近看到一个问题&#xff1a;如果有两个类A和B&#xff0c;A类中有一个B的对象b&#xff0c;B类中有一个A的对象a&#xff0c;那么如何解决这两个类的相互依赖关系呢&#xff0c;几天就给大家说一下Java的循环依赖&#xff0c;raksmart服务器。举个栗子1&#xff1a;可以看到A…

Intellij IDEA 将工程转换成maven工程 详解

1> 右键工程&#xff0c;点击 Add Framework Support2> 选中 Maven&#xff0c;再点击 OK3> 工程根目录自动生成 pom.xml 文件&#xff0c;这样 工程就支持 Maven版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 http://blog.csdn.net/che…

数据结构(七)排序---直接插入排序(稳定)

经典排序算法----直接插入排序算法及其改进&#xff08;稳定&#xff09; 定义&#xff1a; 直接插入排序的基本操作是将一个记录插入到已经排好序的有序表中&#xff0c;从而得到一个新的&#xff0c;记录数加一的有序表。 实现思想 我们预留了一个哨兵&#xff0c;这里我们将…

java嵌套类型 无法隐藏外层类型_java内部类深入详解 内部类的分类 特点 定义方式 使用...

java内部类 内部类的分类 特点 定义方式 使用 外部类调用内部类 多层嵌套内部类 内部类访问外部类属性 接口中的内部类 内部类的继承 内部类的覆盖 局部内部类 成员内部类 静态内部类 匿名内部类内部类定义将一个类定义放到另一个类的内部,这就是内部类内部类与组合是完…

java.io.FileNotFoundException: generatorConfig.xml (系统找不到指定的文件。)

在使用MyBatis的逆向工程生成代码时&#xff0c;一直报错java.io.FileNotFoundException: generatorConfig.xml (系统找不到指定的文件。)&#xff0c;如图 文件结构如下&#xff1a; 代码如下&#xff1a; import java.io.File; import java.util.ArrayList; import java.util…

java机器学习库_Amazon Deep Java Library——Java 机器学习工具箱

近年来&#xff0c;人们对机器学习的兴趣稳步增长。具体来说&#xff0c;现在&#xff0c;企业在各种各样的场景中使用机器学习进行图像识别。它在汽车工业、医疗保健、安全、零售、仓库、农场和农业的自动化产品跟踪、食品识别&#xff0c;甚至通过手机摄像头进行实时翻译等方…

阻抗计算

si9000也可以算 一般有点差异&#xff0c;板厂可以微调 加上滤油&#xff0c;实际阻抗会降低2-3欧 影响最大的是层厚 先选择最薄的芯板&#xff0c;注意差分线的阻抗匹配&#xff0c;间距越小&#xff0c;阻抗小&#xff0c; 转载于:https://www.cnblogs.com/IotI/p/8587277.h…

javascript mqtt 发布订阅消息

js client使用paho-mqtt&#xff0c;官网地址&#xff1a;http://www.eclipse.org/paho/&#xff0c;参考http://www.eclipse.org/paho/clients/js/官网给出例子Getting Started&#xff0c;写出下面简单的测试代码。 <!DOCTYPE html> <html> <head> <met…

用C++调用tensorflow在python下训练好的模型(centos7)

本文主要参考博客https://blog.csdn.net/luoyexuge/article/details/80399265 [1] bazel安装参考:https://blog.csdn.net/luoyi131420/article/details/78585989 [2] 首先介绍下自己的环境是centos7&#xff0c;tensorflow版本是1.7&#xff0c;python是3.6&#xff08;anacond…