How to render a component only if another component is not rendered?

会有一股神秘感。 提交于 2019-12-22 06:57:22

问题


I have a page that the user can access via Android, iPhone, BlackBerry or via an unknown browser. I have 4 rich:panels, one for each platform and the latter is a generic one.

The code:

<rich:panel id="dlAndroid" rendered="#{fn:containsIgnoreCase(request.getHeader('User-Agent'), 'Android')}">
    ...
</rich:panel>

<rich:panel id="dlIphone" rendered="#{fn:containsIgnoreCase(request.getHeader('User-Agent'), 'iPhone')}">
    ...
</rich:panel>

<rich:panel id="dlBlackberry" rendered="#{fn:containsIgnoreCase(request.getHeader('User-Agent'), 'BlackBerry')}">
    ...
</rich:panel>

<rich:panel id="dlGeneric" rendered="#{ ---> WHAT TO WRITE HERE? <--- }">

How can I render the last rich:panel only if none of the others has been rendered?


回答1:


To the point, your question as stated in the title can concretely be answered as:

<rich:panel binding="#{panel1}" ...>
    ...
</rich:panel>
<rich:panel binding="#{panel2}" ...>
    ...
</rich:panel>
<rich:panel binding="#{panel3}" ...>
    ...
</rich:panel>
<rich:panel ... rendered="#{not panel1.rendered and not panel2.rendered and not panel3.rendered}">
    ...
</rich:panel>

However, in this particular case it's perhaps nicer to alias those long winded expressions with <c:set>:

<c:set var="android" value="#{fn:containsIgnoreCase(header['User-Agent'], 'Android')}" scope="request" />
<c:set var="iPhone" value="#{fn:containsIgnoreCase(header['User-Agent'], 'iPhone')}" scope="request" />
<c:set var="blackBerry" value="#{fn:containsIgnoreCase(header['User-Agent'], 'BlackBerry')}" scope="request" />

<rich:panel ... rendered="#{android}">
    ...
</rich:panel>
<rich:panel ... rendered="#{iPhone}">
    ...
</rich:panel>
<rich:panel ... rendered="#{blackBerry}">
    ...
</rich:panel>
<rich:panel ... rendered="#{not android and not iPhone and not blackBerry}">
    ...
</rich:panel>

Note that there's a shorter way to get the request header by the implicit #{header} map.




回答2:


You can use

<c:choose>
<c:when test="#{fn:containsIgnoreCase(request.getHeader('User-Agent'), 'Android')}">
<rich:panel id="dlAndroid">
...
</rich:panel>
</c:when>
<c:when test="#{fn:containsIgnoreCase(request.getHeader('User-Agent'), 'iPhone')}">
<rich:panel id="dlIphone">
...
</rich:panel>
</c:when>
<c:otherwise>
<rich:panel id="dlGeneric">
    ...
</rich:panel>
</c:otherwise>
<c:choose>

I think you are using a logic to determine the browser type which would not change between the POSTS on the same page , so it seems safe to me to use JSTL tag here. JSTL tag will only execute once during CREATE VIEW for the page.

However if you are testing the condition on some model variable then it is better to wrap each of the panels in ui:fragment like

<ui:fragment rendered="#{fn:containsIgnoreCase(request.getHeader('User-Agent'), 'Android')}">
    <rich:panel id="dlAndroid">
    ...
    </rich:panel>
<ui:fragment>



回答3:


You could write this validation on a managed bean method, so it will verify if the user-agent fits the 4th option. Example:

public boolean userAgentUnknownBrowser() {
// Verify if contains the user-agent String
}

And on your page, you'll just use the method:

<rich:panel id="dlGeneric" rendered="#{myBean.userAgentUnknownBrowser()}">


来源:https://stackoverflow.com/questions/14715574/how-to-render-a-component-only-if-another-component-is-not-rendered

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!