我正在JSF(Mojarra 2.1.x)中构建一个简单的组件,我必须访问父ui组件才能更新它们,目前我正在使用绑定来实现这一点,但它只有在我没有的情况下才有效在同一页面上多次使用该组件。
所以我需要一个允许我在同一页面上多次使用该组件的解决方案。
在以下代码中,我使用commandButton
更新binding="#{msButton}"
,使用panel
更新binding="#{msPanel}"
:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:component xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:layout="http://sterz.stlrg.gv.at/jsf/layout"
xmlns:p="http://primefaces.org/ui">
<cc:interface>
<cc:attribute name="controller" required="true" />
<cc:attribute name="converter" required="true" />
</cc:interface>
<cc:implementation>
<p:commandButton id="msButton#{cc.attrs.controller.class.getSimpleName()}" binding="#{msButton}" value="#{msg.mehr} (#{cc.attrs.controller.itemList.size()})" type="button" />
<p:overlayPanel id="msOverlayPanel" for=":#{msButton.clientId}" hideEffect="fade" my="right top" at="right bottom">
<p:panel id="msPanel#{cc.attrs.controller.class.getSimpleName()}" binding="#{msPanel}" styleClass="ui-panel-fit">
<ui:repeat id="repeat" value="#{cc.attrs.controller.itemList}"
var="item">
<p:commandButton id="removeButton"
actionListener="#{cc.attrs.controller.removeItem(item)}"
icon="ui-icon-trash" update=":#{msPanel.clientId} :#{msButton.clientId}" ajax="true"
process="@this" disabled="#{cc.attrs.controller.itemList.size() == 1}"/>
<p:selectBooleanButton id="value1" value="#{item.exclude}"
offLabel="und" onLabel="und nicht" style="width:80px;">
<p:ajax event="change" process="@this" />
</p:selectBooleanButton>
<p:autoComplete converter="#{cc.attrs.converter}"
readonly="#{cc.attrs.readonly}" value="#{item.from}"
dropdown="true"
completeMethod="#{cc.attrs.controller.autocomplete}" var="gp"
itemLabel="#{gp.displayName}" itemValue="#{gp}">
<p:ajax event="itemSelect" process="@this" />
</p:autoComplete>
<h:outputText value=" #{msg.bis} " />
<p:autoComplete converter="#{cc.attrs.converter}"
readonly="#{cc.attrs.readonly}" value="#{item.to}" dropdown="true"
completeMethod="#{cc.attrs.controller.autocomplete}" var="gp"
itemLabel="#{gp.displayName}" itemValue="#{gp}">
<p:ajax event="itemSelect" process="@this" />
</p:autoComplete>
<br />
</ui:repeat>
<hr />
<p:commandButton id="addButton" actionListener="#{cc.attrs.controller.addItem}"
icon="ui-icon-plus" value="#{msg.zufuegen}" update="@parent :#{msButton.clientId}"
ajax="true" process="@this"/>
</p:panel>
</p:overlayPanel>
</cc:implementation>
</ui:component>
任何帮助都非常赞赏。
答案 0 :(得分:1)
解决方案是使用faces组件bean
@FacesComponent("com.xxx.MultiselectorIdComponent")
public class MultiselectorIdComponent extends UINamingContainer
{
UIComponent msPanel;
// getters/settter and other ui compunents
}
告诉组件接口使用哪个组件bean
<cc:interface componentType="com.xxx.MultiselectorIdComponent">
将JSF组件绑定到faces组件bean中的组件
<p:panel binding="#{cc.msPanel}"/>
并访问组件,例如更新组件,我们使用绑定
<p:commandButton value="My Button" update=":#{cc.msPanel.clientId}"/>
同时强>
一个好的做法是使用具有以下ID的父容器(如<div>
)
<div id="#{cc.clientId}">
希望这有帮助, 此致
答案 1 :(得分:0)
您可以按照样式类
定位要更新的组件<p:commandButton styleClass="msButton" ... />
<p:panel styleClass="msPanel" ... />
我想你会从addButton
更新它们,看起来像这样
<p:commandButton id="addButton" update="@(.msButton, .msPanel)" ... />
在同一页面上处理许多cc
个实例应该没有问题。
<强>更新强>
您可以尝试update="@composite"
,这应刷新整个自定义组件。或者,繁琐的update="@parent @parent:@parent:@parent:@child(1)"
分别应该面向面板和按钮。或update="@parent @parent:@parent:@previous"
,也应该这样做。请查看Primefaces User Guide中的第4.3章,了解更多示例和支持的关键字。
答案 2 :(得分:0)
我通过common bean&#34; bindingBean&#34;解决了类似的问题。存储在ViewContext中。 BindingBean保存组件记录的内部MAP中的所有绑定组件。哈希映射的关键是EL表达式 - 它是组件的工厂。 EL用于创建组件。组件保存在存储在绑定bean中的MAP中的记录中。
示例:
<h:panel binding="#{bindBean.get('msPanelFactory.getPanel()').component}"/>
记录:
public class BindingRecord {
private Object component;
private String compExpr;
public BindingRecord(String compExpr) {
this.compExpr = compExpr;
}
public Object getComponent() {
if (component == null) {
component = getValueExprValue("#{" + compExpr + "}");
}
return component;
}
public void setComponent(Object component) {
this.component = component;
}
public Object getStoredComponent() {
return component;
}
}
绑定bean:
public class BindingBean {
private final Map<String, BindingRecord> bindingMap = new HashMap<>();
public BindingRecord get(String key) {
BindingRecord result = bindingMap.get(key);
if (result == null) {
result = new BindingRecord(key);
bindingMap.put(key, result);
}
return result;
}
}
在您的情况下,您可以使用:
<h:panel binding="#{bindingBean.get('panelFactory.create()').component}"/>
在复合组件内部,您可以使用技巧 - 通过复合参数传递组件名称:
<h:panel binding="#{bindingBean.get('panelFactory.create('.concate(cc.attrs.componentName).concate(')')).component}"/>