我正在使用Glassfish 3.2.2和JSF 2.1.11
我正在尝试创建一个复合组件,它将字符串和最大字符数作为参数,然后只显示最大字符数,但它旁边会有一个“更多”链接,单击时会将文本扩展为全长,然后在其旁边显示“less”链接,将其恢复为最大字符数。
我看到一些奇怪的行为,所以我想知道我做错了什么。
这是我的复合组件定义:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:p="http://primefaces.org/ui">
<composite:interface componentType="expandableTextComponent">
<composite:attribute name="name" required="true"/>
<composite:attribute name="maxCharacters" required="true"/>
<composite:attribute name="value" required="true"/>
</composite:interface>
<composite:implementation>
<h:panelGroup id="#{cc.attrs.name}">
<h:outputText value="#{fn:substring(cc.attrs.value, 0, cc.attrs.maxCharacters)}" rendered="#{fn:length(cc.attrs.value) le cc.attrs.maxCharacters}"/>
<h:outputText value="#{fn:substring(cc.attrs.value, 0, cc.attrs.maxCharacters)}" rendered="#{fn:length(cc.attrs.value) gt cc.attrs.maxCharacters and !cc.expanded}" style="margin-right: 5px;"/>
<h:outputText value="#{cc.attrs.value}" rendered="#{fn:length(cc.attrs.value) gt cc.attrs.maxCharacters and cc.expanded}" style="margin-right: 5px;"/>
<p:commandLink actionListener="#{cc.toggleExpanded()}" rendered="#{fn:length(cc.attrs.value) gt cc.attrs.maxCharacters}" update="#{cc.attrs.name}">
<h:outputText value="#{__commonButton.more}..." rendered="#{!cc.expanded}"/>
<h:outputText value="#{__commonButton.less}" rendered="#{cc.expanded}"/>
</p:commandLink>
</h:panelGroup>
</composite:implementation>
</html>
这是Java组件:
@FacesComponent("expandableTextComponent")
public class ExpandableTextComponent extends UINamingContainer
{
boolean expanded;
public boolean isExpanded()
{
return expanded;
}
public void toggleExpanded()
{
expanded = !expanded;
}
}
不幸的是,每次调用toggleExpanded函数时,expand都是false。
但是,如果我将复合组件更改为以下内容,则可以正常工作。
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:p="http://primefaces.org/ui">
<composite:interface componentType="expandableTextComponent">
<composite:attribute name="name" required="true"/>
<composite:attribute name="maxCharacters" required="true"/>
<composite:attribute name="value" required="true"/>
</composite:interface>
<composite:implementation>
<h:panelGroup id="#{cc.attrs.name}">
<h:outputText value="#{fn:substring(cc.attrs.value, 0, cc.attrs.maxCharacters)}" rendered="#{fn:length(cc.attrs.value) le cc.attrs.maxCharacters}"/>
<h:outputText value="#{fn:substring(cc.attrs.value, 0, cc.attrs.maxCharacters)}" rendered="#{fn:length(cc.attrs.value) gt cc.attrs.maxCharacters and !cc.expanded}" style="margin-right: 5px;"/>
<p:commandLink actionListener="#{cc.toggleExpanded()}" rendered="#{fn:length(cc.attrs.value) gt cc.attrs.maxCharacters and !cc.expanded}" update="#{cc.attrs.name}" process="@this">
<h:outputText value="#{__commonButton.more}..."/>
</p:commandLink>
<h:outputText value="#{cc.attrs.value}" rendered="#{fn:length(cc.attrs.value) gt cc.attrs.maxCharacters and cc.expanded}" style="margin-right: 5px;"/>
<p:commandLink actionListener="#{cc.toggleExpanded()}" rendered="#{fn:length(cc.attrs.value) gt cc.attrs.maxCharacters and cc.expanded}" update="#{cc.attrs.name}" process="@this">
<h:outputText value="#{__commonButton.less}"/>
</p:commandLink>
</h:panelGroup>
</composite:implementation>
</html>
如果我在toggleExpanded函数中放置一个断点,它只会在“more”链接上调用,而不是在“less”链接上调用。所以问题是当我点击“less”链接时为什么不调用它?这段代码不应该等同于上面的代码吗?
有没有更好的方法来保存组件中的状态?
答案 0 :(得分:5)
基本上,当您向组件添加自定义属性/属性时,您应该根据他们的文档覆盖UIComponent#saveState()
和restoreState()
,这些属性/属性应该在同一视图上的多个HTTP请求中存活。组件实例即在每个请求上重新创建。
从JSF 2.0开始,更好的方法是直接在属性getters / setters中使用StateHelper
。它可以通过继承的UIComponent#getStateHelper()
方法获得。
private enum PropertyKeys {
expanded;
}
public void toggleExpanded() {
setExpanded(!isExpanded());
}
public void setExpanded(boolean expanded) {
getStateHelper().put(PropertyKeys.expanded, expanded);
}
public boolean isExpanded() {
return (boolean) getStateHelper().eval(PropertyKeys.expanded, false);
}