问题
I have a page that the user can access via Android, iPhone, BlackBerry or via an unknown browser. I have 4 rich:panel
s, 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