JSF复合组件-尝试保存状态时的怪异行为 [英] JSF composite component - weird behavior when trying to save state
问题描述
我正在使用Glassfish 3.2.2和JSF 2.1.11
I'm using Glassfish 3.2.2 and JSF 2.1.11
我正在尝试创建一个复合组件,该组件将以字符串和最大字符数为参数,然后仅显示最大字符数,但是它旁边会有一个更多"链接,即单击该按钮将把文本扩展到完整长度,然后在其旁边有一个较少"链接,可将其带回最大字符数.
I'm trying to create a composite component that will take as parameters a string and a max number of characters and then will show only the max amount of characters, but it will have a "more" link next to it, that when clicked will expand the text to the full length and will then have a "less" link next to it to take it back to the max number of characters.
我看到一些奇怪的行为,所以我想知道我做错了什么.
I'm seeing some weird behavior, so I'm wondering if I'm doing something wrong.
这是我的复合组件定义:
Here is my composite component definition:
<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函数时,expanded始终为false.
Unfortunately expanded is always false every time the toggleExpanded function is called.
但是,如果我将复合组件更改为以下组件,那么它将起作用.
However if I change the composite component to the following then it works.
<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函数中,则只会在更多"链接而不是更少"链接上调用它.所以问题是为什么当我单击较少"链接时为什么不调用它?此代码不应该与上面的代码等效吗?
If I place a breakpoint in the toggleExpanded function, it only gets called on the "more" link and not the "less" link. So the question is why doesn't it get called when I click on the "less" link? Shouldn't this code be equivalent to the code above?
是否有更好的方法来将状态保存在组件中?
Is there a better way to save state in a component?
推荐答案
基本上,您应该覆盖 restoreState()
,当您添加自定义项时组件的属性/属性,应在同一视图上的多个HTTP请求中保留.即会在每个请求上重新创建组件实例.
Basically, you should be overridding UIComponent#saveState()
and restoreState()
according their documentation when you add custom properties/attributes to the component which should survive across multiple HTTP requests on the same view. The component instance is namely recreated on every request.
自JSF 2.0起,更好的方法是使用 StateHelper
直接在属性获取器/设置器中.继承的
Since JSF 2.0, much better is to use the StateHelper
directly in the attribute getters/setters. It's available by the inherited UIComponent#getStateHelper()
method.
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);
}
这篇关于JSF复合组件-尝试保存状态时的怪异行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!