我的facelet页面中有以下代码:
<hc:rangeChooser1 id="range_chooser"
from="#{testBean.from}"
to="#{testBean.to}"
listener="#{testBean.update}"
text="#{testBean.text}">
<f:ajax event="rangeSelected"
execute="@this"
listener="#{testBean.update}"
render=":form:growl range_chooser"/>
</hc:rangeChooser1>
这是我的复合组件:
<ui:component xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui">
<cc:interface componentType="rangeChooser">
<!-- Define component attributes here -->
<cc:clientBehavior name="rangeSelected" event="change" targets="hiddenValue"/>
<cc:attribute name="from" type="java.util.Calendar"/>
<cc:attribute name="to" type="java.util.Calendar"/>
<cc:attribute name="text" type="java.lang.String"/>
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
...
<p:inputText id="hiddenValue" value="#{cc.attrs.text}"/>
...
</div>
</cc:implementation>
</ui:component>
如何将复合组件中的属性from
,to
和text
传递给辅助bean?我的意思是在支持组件中注入这些值,而不是通过
<p:inputText id="hiddenValue" value="#{cc.attrs.text}"/>
更新:还有更正确的定义我需要什么:能够改变我从backing bean
传递到composite component
内的对象{ {1}}的{1}}。因此,当我执行backing component
或composite component
process
时,我会获得更新后的值。
这是我的支持部分:
execute
我无法理解如何继续前进?一般来说,我需要从composite component
获取一个值并将其转换为两个日历对象@FacesComponent("rangeChooser")
public class RangeChooser extends UIInput implements NamingContainer {
private String text;
private Calendar from;
private Calendar to;
@Override
public void encodeBegin(FacesContext context) throws IOException{
super.encodeBegin(context);
}
public String getText() {
String text = (String)getStateHelper().get(PropertyKeys.text);
return text;
}
public void setText(String text) {
getStateHelper().put(PropertyKeys.text, text);
}
/*
same getters and setters for Calendar objects, from and to
*/
}
和<p:inputText id="hiddenValue" value="#{cc.attrs.text}"/>
。
如果有人可以从这里指出我正确的方向,那将是很棒的。 我知道我需要使用from
,但不知道该代码的放置位置。提前感谢您。
答案 0 :(得分:5)
根据您的意见,这是您所期望的。
请注意,即使此实施有效,在概念上也是错误的!
您正在考虑from
和to
作为INPUTS(不是输入组件,而是输入值)和text
作为OUTPUT。这不是JSF的工作方式!
但是,这是
<cc:interface componentType="rangeComponent">
<cc:attribute name="from" />
<cc:attribute name="to" />
<cc:clientBehavior name="rangeSelected" event="dateSelect" targets="from to"/>
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<p:calendar id="from" value="#{cc.attrs.from}"/>
<p:calendar id="to" value="#{cc.attrs.to}"/>
</div>
</cc:implementation>
在页面中使用:
<h:form>
<e:inputRange from="#{rangeBean.from}" to="#{rangeBean.to}" text="#{rangeBean.text}">
<p:ajax event="rangeSelected" process="@namingcontainer" update="@form:output" listener="#{rangeBean.onChange}" />
</e:inputRange>
<h:panelGrid id="output" columns="1">
<h:outputText value="#{rangeBean.from}"/>
<h:outputText value="#{rangeBean.to}"/>
<h:outputText value="#{rangeBean.text}"/>
</h:panelGrid>
</h:form>
使用此支持组件:
@FacesComponent("rangeComponent")
public class RangeComponent extends UINamingContainer
{
@Override
public void processUpdates(FacesContext context)
{
Objects.requireNonNull(context);
if(!isRendered())
{
return;
}
super.processUpdates(context);
try
{
Date from = (Date) getValueExpression("from").getValue(context.getELContext());
Date to = (Date) getValueExpression("to").getValue(context.getELContext());
ValueExpression ve = getValueExpression("text");
if(ve != null)
{
ve.setValue(context.getELContext(), from + " - " + to);
}
}
catch(RuntimeException e)
{
context.renderResponse();
throw e;
}
}
}
使用这个支持bean:
@ManagedBean
@ViewScoped
public class RangeBean implements Serializable
{
private static final long serialVersionUID = 1L;
private Date from = new Date(1000000000);
private Date to = new Date(2000000000);
private String text = "range not set";
public void onChange(SelectEvent event)
{
Messages.addGlobalInfo("[{0}] changed: [{1}]", event.getComponent().getId(), event.getObject());
}
// getters/setters
}
答案 1 :(得分:4)
我使用BalusC tecnique(并且没有PrimeFaces)重写了代码:
形式:
<h:form>
<e:inputRange value="#{rangeBean.range}">
<p:ajax event="change" process="@namingcontainer" update="@form:output"
listener="#{rangeBean.onChange}" />
</e:inputRange>
<h:panelGrid id="output" columns="1">
<h:outputText value="#{rangeBean.range}" />
</h:panelGrid>
</h:form>
复合材料:
<cc:interface componentType="rangeComponent">
<cc:attribute name="value" />
<cc:clientBehavior name="change" event="change" targets="from to"/>
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<h:inputText id="from" binding="#{cc.from}">
<f:convertDateTime type="date" pattern="dd/MM/yyyy" />
</h:inputText>
<h:inputText id="to" binding="#{cc.to}">
<f:convertDateTime type="date" pattern="dd/MM/yyyy" />
</h:inputText>
</div>
</cc:implementation>
支持组件:
@FacesComponent("rangeComponent")
public class RangeComponent extends UIInput implements NamingContainer
{
private UIInput from;
private UIInput to;
@Override
public String getFamily()
{
return UINamingContainer.COMPONENT_FAMILY;
}
@Override
public void encodeBegin(FacesContext context) throws IOException
{
String value = (String) getValue();
if(value != null)
{
String fromString = StringUtils.substringBefore(value, "-");
String toString = StringUtils.substringAfter(value, "-");
try
{
from.setValue(from.getConverter().getAsObject(context, from, fromString));
}
catch(Exception e)
{
from.setValue(new Date());
}
try
{
to.setValue(to.getConverter().getAsObject(context, to, toString));
}
catch(Exception e)
{
to.setValue(new Date());
}
}
super.encodeBegin(context);
}
@Override
public Object getSubmittedValue()
{
return (from.isLocalValueSet() ? from.getValue() : from.getSubmittedValue()) + "-" + (to.isLocalValueSet() ? to.getValue() : to.getSubmittedValue());
}
@Override
protected Object getConvertedValue(FacesContext context, Object submittedValue)
{
return from.getSubmittedValue() + "-" + to.getSubmittedValue();
}
public UIInput getFrom()
{
return from;
}
public void setFrom(UIInput from)
{
this.from = from;
}
public UIInput getTo()
{
return to;
}
public void setTo(UIInput to)
{
this.to = to;
}
}
和托管bean:
@ManagedBean
@ViewScoped
public class RangeBean implements Serializable
{
private static final long serialVersionUID = 1L;
private String range = "01/01/2015-31/12/2015";
public void onChange(AjaxBehaviorEvent event)
{
Messages.addGlobalInfo("[{0}] changed: [{1}]", event.getComponent().getId(), event.getBehavior());
}
public String getRange()
{
return range;
}
public void setRange(String range)
{
this.range = range;
}
}
请注意,托管bean仅为get / set保留range
属性。 From
和to
已消失,支持组件会自行派生并重建它们。