6

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?

Alex Oliveira
  • 843
  • 8
  • 23
  • 1
    Have you tried the ugliest solution? `rendered="#{not(fn:containsIgnoreCase(request.getHeader('User-Agent'), 'Android') or fn:containsIgnoreCase(request.getHeader('User-Agent'), 'iPhone') or fn:containsIgnoreCase(request.getHeader('User-Agent'), 'BlackBerry'))}"`? – Luiggi Mendoza Feb 05 '13 at 22:14
  • @LuiggiMendoza I tried something similar, but not this way, because I was trying to do not repeat this lines of code. But despite being ugly, your solution works. – Alex Oliveira Feb 06 '13 at 12:48

3 Answers3

5

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.

BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • . By using statements like this again we are mixing up view and business logic which violates the concept of MVC. How do you justify this ? – Krsna Chaitanya Feb 06 '13 at 08:16
  • @Krsna: Is it (re)used anywhere in business logic? Then keep it there. Is it used exclusively in the view? Then it doesn't harm to keep it in the view. – BalusC Feb 06 '13 at 10:57
0

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()}">
Diogo Moreira
  • 967
  • 1
  • 8
  • 21
0

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>
Avinash Singh
  • 2,564
  • 1
  • 14
  • 20