【问题标题】:JSF/Facelets: set `action` attribute to a dynamically evaluated stringJSF/Facelets:将 `action` 属性设置为动态评估的字符串
【发布时间】:2009-08-06 07:35:48
【问题描述】:

在我的 JSF/Facelets 应用程序中,我想使用自定义标记从页面 ID 列表动态生成面包屑路径:

<foo:breadcrumbs trail="foo,bar,baz"/>

这应该会生成如下内容:

<h:commandLink action="foo" ... />
<h:commandLink action="bar" ... />
<!-- (etc.) -->

我的代码如下所示:

<ui:repeat value="#{fn:split(trail, ',')}" var="key">
    <h:commandLink action="#{key}" ... /> 
</ui:repeat>

这段代码的问题是#{key} 被解释为一个方法绑定。但是,我只想将 #{key} 的字符串值作为导航结果返回。我怎样才能做到这一点?


我唯一能想到的就是创建一个具有outcome 字段和操作处理程序的虚拟托管bean,然后像这样调用它:

<h:commandLink action="#{dummy.click}" ...>
    <f:setPropertyActionListener target="#{dummy.outcome}" value="#{key}" />
</h:commandLink>

虚拟类定义如下:

public class Dummy {

    private String outcome;

    public String click() {
        return outcome;
    }

    public void setOutcome(String outcome) {
        this.outcome = outcome;
    }

    public void getOutcome() {
        return outcome;
    }
}

这看起来很难看,我不知道它是否会起作用。

【问题讨论】:

    标签: jsf navigation facelets breadcrumbs


    【解决方案1】:

    自从提出这个问题后,我发现了一个显而易见的解决方案,而且实施起来非常简单。

    作为 JSF 操作目标的方法必须不接受任何参数并返回一个字符串。 原来 String 类已经有了一个匹配这个签名的方法——toString()!

    因此,我已将 UI 循环更改为以下内容:

    <ui:repeat value="#{fn:split(trail, ',')}" var="key">
        <h:commandLink action="#{key.toString}" ... /> 
    </ui:repeat>
    

    这允许动态评估的key 成为 JSF 操作结果,并且不需要任何额外的类或丑陋的骇客。

    【讨论】:

      【解决方案2】:

      我想到了几种方法。

      选项 1

      坚持使用commandLink,直接从action binding中的request map中读取var:

      public String click() {
        FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext extContext = context.getExternalContext();
        Map<String, Object> reqMap = extContext.getRequestMap();
        return (String) reqMap.get("uirepeatVar");
      }
      

      (转发器的属性为var="uirepeatVar"。)


      选项 2

      切换到outputLink 并在服务器上建立 GET 链接:

      public List<String> getViewUrls() {
        List<String> views = Arrays.asList("/index.xhtml", "/idtable.xhtml");
      
        List<String> urls = new ArrayList<String>();
        FacesContext context = FacesContext.getCurrentInstance();
        Application application = context.getApplication();
        ViewHandler viewHandler = application.getViewHandler();
        for (String view : views) {
          String url = viewHandler.getActionURL(context, view);
          urls.add(url);
        }
        return urls;
      }
      

      查看:

      <ui:repeat value="#{breadcrumbBean.viewUrls}" var="url">
        <h:outputLink value="#{url}">#{url}</h:outputLink> <br />
      </ui:repeat>
      

      【讨论】:

      • 嗯...我不想使用outputLinks。当我混合搭配commandLinks 和outputLinks 时,我似乎一直遇到麻烦。对于我的应用程序内链接,我更愿意坚持使用 commandLinks
      • 然后使用第一个选项 - 直接从请求映射中读取 var。
      【解决方案3】:

      为什么不创建一个以编程方式生成 h:commandLink 对象的自定义组件?这可能是“最干净”的解决方案。

      【讨论】:

      • 这听起来是个好主意,但我不知道该怎么做。你能指出我正确的方向吗?
      • 网上有很多教程。例如,IBM developerWorks 教程:ibm.com/developerworks/views/java/…:
      • 我认为在这种情况下自定义组件可能有点过头了,但如果你走这条路,编码/解码多个链接的单个控件就可以解决问题。
      猜你喜欢
      • 2011-09-11
      • 2013-06-28
      • 1970-01-01
      • 1970-01-01
      • 2011-06-03
      • 2016-08-29
      • 2011-05-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多