【问题标题】:JSF Access viewParams from within a componentJSF 从组件中访问 viewParams
【发布时间】:2013-09-15 21:40:38
【问题描述】:

我有一个组件来显示一个条目。这个组件可以在同一个页面中出现多次,因此只需要一个实体,将它传递给组件的支持 bean,所有的魔法都会在这里发生。

组件的外观会受到各种参数的影响。

现在,一个要求是,无论我有 1 个还是 10 个这些组件,“相同”的视图状态都应该可以使用深度链接恢复。

假设我的组件如下所示:

<composite:interface componentType="itemView" >
  <composite:attribute name="item" required="true" shortDescription="The item to display."/>
  <composite:attribute name="urlPrefix" required="true" />
</composite:interface>

<composite:implementation>
    <f:event type="preRenderComponent" listener="#{cc.init}" />

   ....     
</composite:implementation>

它有对应的backing Bean,我可以访问。 (省略这个,因为它不是必需的)

现在,这些组件被嵌入到一个页面中,如下所示:

   <f:metadata>
        <f:viewParam name="itemType"
            value="#{listController.itemType}"></f:viewParam>

    </f:metadata>

    <ui:define name="content">

    <!-- multiple occurences, ui repeat over list of items -->
    <my:itemView item="#{currentItem}" urlPrefix="#{listController.nextLetter}">

如前所述,每个项目的状态都可能受到影响,并且更改后的状态必须可以通过深层链接访问。所以,我的想法是,在组件内部使用&lt;h:link&gt;,为每个属性添加前缀并使用includeViewParams="true",这样每个(非默认)状态都是url的一部分。

<composite:interface componentType="itemView" >
  <composite:attribute name="item" required="true" shortDescription="The item to display."/>
  <composite:attribute name="urlPrefix" required="true" />
</composite:interface>

<composite:implementation>
    <f:event type="preRenderComponent" listener="#{cc.init}" />

 <h:link includeViewParams="true">
<f:param name="#{cc.attrs.urlPrefix}size" value="#{cc.largerSize}" />
    larger 
  </h:link>

   ....     
</composite:implementation>

就像“更大”的链接一样,最多有 10 个链接,提供不同的选项。

问题: include-view-params 是否包含 same 组件中的所有视图参数,以及它的父组件(itemType ),但不是来自其他组件。所以,基本上改变“一个”组件的样式,会丢弃另一个组件的参数。

预期: 该网址已经看起来像?itemType=something&amp;asize=5&amp;abackground=green 单击 b 组件上的“更大”链接将给我:?itemType=something&amp;asize=5&amp;abackground=green&amp;bsize=5

发生了什么: 点击链接后,网址如下:?itemType=something&amp;bsize=5 所以“a”的属性被删除了。

我注意到,如果我使用 &lt;f:viewParam name="asize" /&gt; 之类的东西扩展列表页面上的 &lt;f:metadata&gt; 对象,则在单击“b”中的某些内容时,aSize 参数将被保留 - 但当然,如果我需要列出像这样的所有参数,我不需要组件,因为我无法预测项目的数量。

所以,我尝试在组件内添加它(如 f:event):&lt;f:viewParam name="#{cc.urlPrefix}size" /&gt; - 但那不起作用。

对此有任何想法(或替代解决方案?注意:将视图状态保存在数据库中,简单地使用“单一”ID 来引用该状态基本上是不好的,因为这会导致大量数据污染。视图-状态需要保持瞬态,但可以恢复:0))

【问题讨论】:

    标签: jsf request components viewparams


    【解决方案1】:

    终于找到了解决办法。这不是最好的,但至少可以工作 ;)

    我在组件的 bean 上创建了一个方法,它将返回一个查询字符串,其中包含除作为参数传递的值之外的所有值。

    所以,每当我想更改参数asize=5 时,我都会使用参数size 调用此函数并附加新参数(函数将仅在前缀匹配时排除此参数,因此没有其他组件风格会受到影响。):

    public String buildUrlWithout(String keyString) {
            List<String> keys = ConversionHelper.Explode(keyString, ",");
    
            // get all parameters from the url.
            String prefix = this.getAttributes().get("urlPrefix").toString();
            ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
    
            Map<String, String> params = externalContext.getRequestParameterMap();
            List<KeyValuePair<String, String>> result = new LinkedList<KeyValuePair<String, String>>();
    
            outerfor: for (Map.Entry<String, String> kvp : params.entrySet()) {
                for (String s : keys) {
                    if (kvp.getKey().equals(prefix + s)) {
                        continue outerfor;
                    }
                }
    
                // keep param
                result.add(new KeyValuePair<String, String>(kvp.getKey(), kvp.getValue()));
            }
    
            String qStr = KeyValuePair.toQueryString(result);
            return qStr;
        }
    

    KeyValuePair 只是一个 Helper-Class,其行为类似于 Map&lt;S,T&gt;,但提供了多个功能,例如 join()split() 等。(在本例中使用 toQueryString()

    最后,在一个组件中,我这样使用:

    <h:outputLink
      value="#{cc.buildUrlWithout('size')}&amp;#{cc.attrs.urlPrefix}size={cc.size +1}">
        larger
    </h:outputLink>
    
    <h:outputLink
      value="#{cc.buildUrlWithout('size')}&amp;#{cc.attrs.urlPrefix}size={cc.size -1}">
        smaller
    </h:outputLink>
    
    <h:outputLink
      value="#{cc.buildUrlWithout('background,border')}&amp;#{cc.attrs.urlPrefix}background=red&amp;#{cc.attrs.urlPrefix}border=green">
        red background + green border
    </h:outputLink>
    

    【讨论】:

      猜你喜欢
      • 2012-12-12
      • 1970-01-01
      • 2012-03-15
      • 1970-01-01
      • 1970-01-01
      • 2011-12-17
      • 2012-06-19
      • 1970-01-01
      • 2011-11-13
      相关资源
      最近更新 更多