The requirement to hide portlets if they are empty is common, but there is no built-in mechanism for this in WebSphere Portal prior to version 6. There is one relatively simple approach, however, that uses client-side JavaScript. Here's how it works in brief:

  1. The portlet skin is wrapped by an HTML element that is given a unique DOM ID for the portlet instance on the page. This will be the outermost container for the portlet.
  2. The content area of the portlet is also given a unique DOM ID.
  3. Javascript is placed at the bottom of the portlet skin which inspects the contents of the content area at runtime. If the contents are empty (or contain some known String flag), the outermost container is hidden at runtime.

Now let's examine these steps again in more detail and with some concrete examples:

Create an outermost containing element with a DOM ID in the portlet skin

First, you'll want to create a custom portlet skin or modify your existing skin(s) for this functionality. The primary skin file is usually Control.jsp. Make sure that the portlet is is contained by an outermost HTML element with a unique ID. The unique DOM ID should be generated in part by the <wps:portletID/> tag so that it is guaranteed to be unique on the rendered page and so that it will indeed be the proper id for the specific portlet.

Portlet skin code (Control.jsp) - example 1

<!-- portlet skin start -->
<%@ page session="false" buffer="none" %>
<%@ taglib uri="/WEB-INF/tld/engine.tld" prefix="wps" %>
<wps:constants/>

<div class="skinNormal" id="portlet_<wps:portletID/>" style="margin-top:8px; margin-left:15px;">
<!-- The rest of your portlet skin code will go here... -->
</div>
<!-- portlet skin ends -->

Create the innermost content element that will be evaluated as empty or full

Next, you'll need an innermost element that may contain rendered data (i.e. content). This is the container that will be evaluated for inner contents (i.e. empty or full). You can either evaluate for empty or look for a special String flag that your portlets produce ("noContent" for example). Looking for a flag may be more ideal because if the portlet returns an error message, it will not be evaluated as empty. You may also want to inspect for the existence of the error message and hide the portlet if that error message exists.

Portlet skin code (Control.jsp) - example 2

<!-- portlet skin start -->
<%@ page session="false" buffer="none" %>
<%@ taglib uri="/WEB-INF/tld/engine.tld" prefix="wps" %>
<wps:constants/>

<div class="skinNormal" id="portlet_<wps:portletID/>" style="margin-top:8px; margin-left:15px;">
  <div class="content" id="content_<wps:portletID/>">
      <wps:portletRender> 
            <font COLOR="red"><wps:problem bundle="nls.problem"/></font>
      </wps:portletRender>
  </div>
</div>
<!-- portlet skin ends -->

Create javascript at the end of the portlet skin that evaluates and hides the portlet if necessary

Finally, you must add javascript at the end of your portlet skin which actually does the evaluation and hides the portlet if necessary. This bit of JavaScript will access the HTML elements in the DOM by their given portlet id. It can then inspect the contents. If the content is empty, or contains a special flag ("^^EMPTY^^" for example), the portlet's outermost container will be hidden (via JavaScript style.display="none" on the element).

Portlet skin code (Control.jsp) - example 3

<!-- portlet skin start -->
<%@ page session="false" buffer="none" %>
<%@ taglib uri="/WEB-INF/tld/engine.tld" prefix="wps" %>
<wps:constants/>

<div class="skinNormal" id="portlet_<wps:portletID/>" style="margin-top:8px; margin-left:15px;">
  <div class="content" id="content_<wps:portletID/>">
      <wps:portletRender> 
            <font COLOR="red"><wps:problem bundle="nls.problem"/></font>
      </wps:portletRender>
  </div>
</div>
<script type="text/javascript">
     // Get a handler on the DOM elements and actual textual content (if it exists)
     var thisPortletElement = document.getElementById('portlet_<wps:portletID/>');
     var thisContentElmement = document.getElementById('content_<wps:portletID/>');
     var thisContent = thisContentElement.innerText();
     // Trim the textual content (usually, your trim is in a global JS function)...
     thisContent = thisContent.replace(/^\s+|\s+$/g, '') ;
     // If the content is empty or contains a special flag string, hide the portlet
     if(thisContent.length == 0 || thisContent.indexOf('^^^EMPTY^^^') != -1){
           thisPortletElement.style.display = "none";
     }
</script>
<!-- portlet skin ends -->

That's it! Hopefully I got the code in correct without any syntax errors (I just recounted this from memory). I used variables in the JavaScript above to make the example understandeable. You may want to initialize those variable in a global JavaScript (in the theme) since the same variables may be used by several portlets; but you get the idea.

Additional notes for WCM Content Display portlets

  • If a WCM portlet gets all of its rendered content via a PZN Component and a personalization rule, the portlet will not display by default if the rule returns no results (i.e. the above approach is not needed).
  • If a WCM portlet gets all of its rendered content via a Menu Component, the portlet will display regardless of whether or not the Menu Component returned items (i.e. the above approach is needed).



There are currently no attachments on this page.

Labels:

Enter labels to add to this page:
Wait Image 
Tip: Looking for a label? Just start typing.