JSF/Facelets:将“action”属性设置为动态评估的字符串

发布于 2024-07-30 02:28:15 字数 1169 浏览 3 评论 0原文

在我的 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>

此代码的问题是 < code>#{key} 被解释为方法绑定。 但是,我只想返回 #{key} 的字符串值作为导航结果。 我怎样才能实现这个目标?


我唯一能想到的就是创建一个虚拟托管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;
    }
}

虽然这看起来很难看,但我不知道它是否有效。

In my JSF/Facelets application, I want to dynamically generate a breadcrumb trail from a list of page IDs using a custom tag:

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

This should generate something like:

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

My code looks something like this:

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

The problem with this code is that #{key} is interpreted as a method binding. However, I just want the string value of #{key} to be returned as the navigation outcome. How can I achieve this?


The only thing I could think of was creating a dummy managed-bean that has an outcome field and an action handler, and invoke it like so:

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

with the dummy class defined like so:

public class Dummy {

    private String outcome;

    public String click() {
        return outcome;
    }

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

    public void getOutcome() {
        return outcome;
    }
}

That seems ugly though, and I don't know if it would work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

云柯 2024-08-06 02:28:16

我想到了几种方法。

选项 1

坚持使用 commandLink 并直接从操作绑定中的请求映射读取 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" code>.)


选项 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>

A couple of ways spring to mind.

Option 1

Stick with commandLink and read the var directly from the request map in the action binding:

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

(Where the repeater has the attribute var="uirepeatVar".)


Option 2

Switch to an outputLink and build GET links on the server:

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;
}

View:

<ui:repeat value="#{breadcrumbBean.viewUrls}" var="url">
  <h:outputLink value="#{url}">#{url}</h:outputLink> <br />
</ui:repeat>
请持续率性 2024-08-06 02:28:16

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

Why don't you create a custom component which generates the h:commandLink objects programmatically? It would probably be the 'cleanest' solution.

不必了 2024-08-06 02:28:15

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

作为 JSF 操作目标的方法必须不接受任何参数并返回一个字符串。
事实证明,String 类已经有一个与此签名匹配的方法 - toString()

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

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

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

Since asking this question, I've discovered an obvious solution that is very simple to implement.

A method that is the target of a JSF action must accept no arguments and return a String.
It turns out that the String class already has a method that matches this signature - toString()!

So, I've changed my UI loop to the following:

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

This allows the dynamically evaluated key to be the JSF action outcome, and doesn't require any additional classes or ugly hackery.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文