JSF2/Facelets中的私有/作用域变量?

发布于 2024-11-15 17:27:05 字数 2390 浏览 3 评论 0原文

我可能没有正确思考 JSF 中的可视组件,但我想这是我问题的一部分。我的问题是关于 JSF中声明的变量似乎缺乏范围。实施。

所以,假设我有 /resources/comp/myPanel.xhtml:

<?xml version="1.0" encoding="UTF-8" ?>
<ui:component xmlns="http://www.w3.org/1999/xhtml"
              xmlns:h="http://java.sun.com/jsf/html"
              xmlns:f="http://java.sun.com/jsf/core" 
              xmlns:ui="http://java.sun.com/jsf/facelets"
              xmlns:c="http://java.sun.com/jsp/jstl/core"      
              xmlns:cc="http://java.sun.com/jsf/composite">
    <cc:interface>
    </cc:interface>
    <cc:implementation>
        <f:loadBundle var="bundle" basename="panelOnly.bundle" />

        <h:outputText value="#{bundle.myText}" />
    </cc:implementation>
</ui:component>

并且有一个资源包加载到该组件中, panelOnly/bundle.properties:

myText = This is a panel resource

然后我有一个放置 myPanel 组件的页面, mainPage.xhtml:

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core" 
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:comp="http://java.sun.com/jsf/composite/comp">
    <h:body>
        <f:view>
            <f:loadBundle basename="mainPage.bundle" var="bundle" />

            <comp:myPanel />

            <h:outputText value="#{bundle.myText}" />
        </f:view>
    </h:body>
</html>

和在主页 mainPage/bundle.properties 中加载了一个资源包:

myText = This is a main page resource

现在,我假设我的页面应该呈现为:

This is a panel resource
This is a main page resource

但是,相反,我得到:

This is a panel resource
This is a panel resource

我认为这是因为我破坏了我的组件中“bundle”符号所指的内容,以便当 mainPage.xhtml 尝试解析该值时,它会查找组件的“bundle”对象而不是原始 mainPage 的。

迄今为止,我的解决方法是在组件中使用唯一的命名变量,这些变量永远不会与主页上的变量发生冲突。但我更希望有一种方法可以让 JSF 将我的组件中声明的任何内容识别为本地范围的变量,并且不会破坏调用者的符号。

我认为有一些标签和其他标签可以用来在 #{cc.attrs...} 下创建本地范围的变量。如果您可以在答案中枚举我的本地范围选项,那将非常有帮助。我怀疑我的是一种特殊情况,也许没有解决方法,因为它不是用设计的。记住。

谢谢!

PS 我正在运行 Mojarra 2.1.1 (FCS 20110408)

(针对格式和复制粘贴错误进行了编辑,2011 年 6 月 15 日)

I might not be thinking correctly in terms of visual components in JSF, but I guess that's part of my question. My question is around the seeming lack of scope around variables declared within JSF <ui:component> implementations.

So, say I have /resources/comp/myPanel.xhtml:

<?xml version="1.0" encoding="UTF-8" ?>
<ui:component xmlns="http://www.w3.org/1999/xhtml"
              xmlns:h="http://java.sun.com/jsf/html"
              xmlns:f="http://java.sun.com/jsf/core" 
              xmlns:ui="http://java.sun.com/jsf/facelets"
              xmlns:c="http://java.sun.com/jsp/jstl/core"      
              xmlns:cc="http://java.sun.com/jsf/composite">
    <cc:interface>
    </cc:interface>
    <cc:implementation>
        <f:loadBundle var="bundle" basename="panelOnly.bundle" />

        <h:outputText value="#{bundle.myText}" />
    </cc:implementation>
</ui:component>

And there is a resource bundle that gets loaded in that component, panelOnly/bundle.properties:

myText = This is a panel resource

And then I have a page that places the myPanel component, mainPage.xhtml:

<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core" 
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:comp="http://java.sun.com/jsf/composite/comp">
    <h:body>
        <f:view>
            <f:loadBundle basename="mainPage.bundle" var="bundle" />

            <comp:myPanel />

            <h:outputText value="#{bundle.myText}" />
        </f:view>
    </h:body>
</html>

and there is a resource bundle that gets loaded in the main page, mainPage/bundle.properties:

myText = This is a main page resource

Now, I would assume that my page should render as:

This is a panel resource
This is a main page resource

But, instead, I get:

This is a panel resource
This is a panel resource

And I assume that is because I clobbered what the "bundle" symbol refers to in my component so that when the mainPage.xhtml tries to resolve that value, it looks to the component's "bundle" object and not the original mainPage's.

My workaround to date has been to just use unique named variables within my components that would never clash with variables on my main pages. But I would prefer if there was a way to coax JSF to recognize anything declared in my component as locally scoped variables and not clobber the caller's symbols.

I think there are and other tags that one can use to make locally scoped variables under #{cc.attrs...}. If you could enumerate my local scoping options in your answer, that would be very helpful. I suspect my <f:loadBundle> is a special case, and maybe there isn't a workaround for that one as it was not designed with <ui:component> in mind.

Thanks!

P.S. I'm running Mojarra 2.1.1 (FCS 20110408)

(edited for formatting and copy and paste bugs 6/15/2011)

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

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

发布评论

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

评论(1

落叶缤纷 2024-11-22 17:27:05

不幸的是,这就是 的工作原理。这是整个视图的一次性设置。并且同一视图中的任何后续 调用都将覆盖前一个调用。

最好的选择是通过支持组件来管理它。

<cc:interface componentType="myPanel">

用作

@FacesComponent(value="myPanel")
public class MyPanel extends UIComponentBase implements NamingContainer {

    private ResourceBundle bundle;

    public MyPanel() {
        bundle = ResourceBundle.getBundle("panelOnly.bundle", 
            FacesContext.getCurrentInstance().getViewRoot().getLocale());
    }

    @Override
    public String getFamily() {
        return "javax.faces.NamingContainer";
    }

    public ResourceBundle getBundle() {
        return bundle;
    }

}

可以

<cc:implementation>
    <h:outputText value="#{cc.bundle.myText}" />
</cc:implementation>

Unfortunately, that's how <f:loadBundle> works. It's an one-time setting for the entire view. And any subsequent <f:loadBundle> calls in the same view will just override the previous one.

Your best bet is to manage it by a backing component.

<cc:interface componentType="myPanel">

with

@FacesComponent(value="myPanel")
public class MyPanel extends UIComponentBase implements NamingContainer {

    private ResourceBundle bundle;

    public MyPanel() {
        bundle = ResourceBundle.getBundle("panelOnly.bundle", 
            FacesContext.getCurrentInstance().getViewRoot().getLocale());
    }

    @Override
    public String getFamily() {
        return "javax.faces.NamingContainer";
    }

    public ResourceBundle getBundle() {
        return bundle;
    }

}

which can be used as

<cc:implementation>
    <h:outputText value="#{cc.bundle.myText}" />
</cc:implementation>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文