JSF复合组件-尝试保存状态时的怪异行为 [英] JSF composite component - weird behavior when trying to save state

查看:105
本文介绍了JSF复合组件-尝试保存状态时的怪异行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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?

推荐答案

基本上,您应该覆盖

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆