Blog Archives

November 15th, 2010
11:56 am
Namespace error when using JSTL in Facelets with JSF 2.0

Posted under JSF
Tags , , , , ,

Update 6/7/2011

I hit this problem again when accidentally ignoring the Eclipse warning.
This time, the problem prevented <c:if> tags from working correctly – the tags always tested as true. This was especially nasty as the cause did not appear related to the problem I was having. See this issue in Mantis about the problem.

Original Post

I was using the following namespace declaration in order to use JSTL (c:if etc.) on a Facelets/JSF 2.0 page, as I had done successfully previously under JSF 1.2:-

xmlns:c=”http://java.sun.com/jstl/core

This gave rise to the following warning in Eclipse:-

NLS missing message: CANNOT_FIND_FACELET_TAGLIB in: org.eclipse.jst.jsf.core.validation.internal.facelet.messages

The namespace is incorrect, and as pointed out here (in Ryan Lubke’s comment on the post) should now be:-

xmlns:c=”http://java.sun.com/jsp/jstl/core

This fixed the problem. A complete listing of the namespaces for the tag libraries is also available in edition 3 of Core JavaServer Faces, at the start of Chapter 4, page 101 – (edition 2 did not have this table; it is a useful addition).

No Comments »

November 11th, 2010
12:59 pm
Scrollable containers in Primefaces

Posted under CSS
Tags , , ,

Some Primefaces containers appear to support scrolling, but this is not universally supported. Layout panels support it, but ordinary panels appear not to.

Fortunately, with IE7 and above, scrolling on a <div> (JSF panelGroup with layout=”block”) works reliably and consistently across modern browsers, so scrolling can just be added within e.g. within a CSS class rule as follows:-

.ss-scroll {
   overflow:auto;
}

or:-

.ss-scroll {
   overflow: scroll;
}

Using overflow:auto will only add the scrollbars if they are needed, i.e. if content is clipped. Using overflow: scroll will add them all the time so you will get redundant scrollbars when the content does not clip.

Note that for Primefaces, to make a scrolling panel for example, the attribute needs to be added to a containing div inside the panel, and not the panel itself, otherwise the panel header will scroll out of view when the contents scroll which is undesirable.

The w3schools documentation on overflow will be found here.

No Comments »

November 11th, 2010
11:35 am
Fonts reduce in size when Primefaces table moved inside a panel

Posted under CSS
Tags , , , ,

Update 22/09/2011

The following selector (as documented below) did not work when used for a particular table. CSS ignored the rule presumably for reasons of specificity:-

.ss-nested-widget, .ss-nested-widget .ui-datatable {
     font-size: 100% !important;
}

However, the following selector did work (and was also modified to include a dialog as well as a table). This has the advantage of not relying on having ss-nested-widget as a class on the table in order to work.
This has now been adopted as standard as the solution for this issue :-

.ss-nested-widget,
.ui-widget .ui-datatable,
.ui-widget .ui-dialog { 
     font-size:100% !important;   
}

Original Post

This issue is due to font size inheritance.

My default font for all Primefaces components was specified globally as follows:-

.ui-widget {

font-size: 75% !important;

}

The reason for this is that in general it is considered more flexible to go for percentage sizes as these can then be scaled automatically when viewed on smaller devices.

Unfortunately, it appears that when for example a table is nested inside a panel, the font size appears to be 75% of 75% as the rule is inherited and applied twice, as 75% is a relative measurement, The table ends up rendered as a 9px font which is too small. The situation is further complicated by the fact that in the Primefaces skinning, there is a mixture of fonts specified in ems, percentages and pixel sizes, which means that not everything is specified in relative sizing anyway.

There are 2 solutions to the issue, both are straightforward, 1/ is the simplest although arguably not the best due to absolute sizing:-

1/ Change the global ui-widget rule above to use a fixed font size (12px works as a replacement for the above 75%)

.ui-widget {

font-size: 12px !important;

}

2/ Keep the  75%  for ui-widget and introduce a new rule to specify a 100% size for nested elements:-

.ss-nested-widget {

font-size:100% !important;

}

This rule needs to be introduced inside the panel. If it is placed on the panel itself, which is the parent element, then the font size just ‘goes large’ to 100%, i.e. larger than the desired default font. To obtain the correct behaviour, the sub-elements inside the panel must be tagged with the style class. It is possible to tag an enclosing <div> just inside the panel, so that the sub-elements inherit it. However, whilst this worked for input selectors and buttons in the panel, tables refused to play ball, and the following rule was needed to ensure that a table in the panel inherited the correct size:-

.ss-nested-widget, .ss-nested-widget .ui-datatable {

font-size: 100% !important;

}

The same kind of trick can be used to target other nested elements which do not inherit the correct size.

An alternative method would be just to add the class to sub-elements individually where required.

No Comments »

November 9th, 2010
6:54 pm
Fetching the old value in a JSF input validator

Posted under JSF
Tags , ,

In my case, I did this when checking string uniqueness in a table – if the value entered was unchanged, this would give a duplicate. Whilst I could in theory detect when I was comparing with the old value, this was hard in practice as I did not know which row I was on.

This trick is a good way of not bothering with validation if the field is unchanged. Note the need to cast the UIComponent passed in the event to a UIInput in order to expose the getValue method. Sample code is as follows :-

String oldValue = ((UIInput)component).getValue().toString().trim();

No Comments »

November 8th, 2010
3:11 pm
Changing Primefaces Structural CSS – Thin Panel example

Posted under JSF
Tags , , ,

Update 10/5/2011

The example project which contains this example is PrimeThemeSwitcherTableNonCC, on page ThinPanel.xhtml. This project may be found in the repository here.

Note that the styling for the repository version has changed slightly from below and is as follows:-

div.ss-thinpanel.ui-panel{
    padding:0px !important;
    border-top-width: 1px !important;
    border-right-width: 1px !important;
    border-bottom-width: 1px !important;
    border-left-width: 1px !important;
    margin-bottom: 1px !important;
}
.ss-thinpanel > div.ui-panel-titlebar {
    padding-top: 4px !important;
    padding-bottom: 3px !important;
    border:none !important;
}

 

Original Post

Sometimes it is desirable to change not the skin of a component but its structure – size, borders etc.
One example of mine was when I wanted an accordion like component which allows multiple panels to be open simultaneously. The accordion used to allow this but does not any longer. A good alternative to the accordion in this case is a stack of panel components, as they can all have independent expand/collapse buttons, and the close button is optional and so can be removed. As a bonus, a submenu can be added if desired as shown in the component showcase.

My issue with the panel for this use case was simply that it looked too chunky and took up too much real estate on the screen when a stack of them was present. I therefore produced some alternative structural CSS to produce a weight watcher’s version of panel, with the aim that a stack of them would take up no more vertical space than a similar stack of the same number of accordion tabs. In fact, in the end my weight watcher’s panel has ended up slightly slimmer than the accordion.

The following example page shows a stack of 3 standard ‘full fat’ panels followed by a similar stack of 3 of the thin version.
Note the following important points about the way the CSS is implemented:-

  • The CSS selectors are all driven by the CSS class ss-thinpanel. Simply including this in the styleClass attribute of the p:panel component enables the thin version.
  • As the new version is tied to the new class ss-thinpanel I have done nothing in CSS which would affect existing use of the panel component – as the example shows, the old can be used alongside the new.
  • The CSS overrides the structural CSS for the panel component, not the skinning CSS. This way, the changes work consistently across all the themes and do not require any theme changes to be made.
  • This technique is useful for any occasion where an alternative flavour of a component is needed – just ensure that the structural CSS is targeted (so all themes work), and drive the change by a new CSS class name. You can then have a number of alternative flavours of a component which are useable just by including the required classname.

<!DOCTYPE HTML>
<html xmlns="http://www.w3c.org/1999/xhtml"
   xmlns:f="http://java.sun.com/jsf/core"
   xmlns:h="http://java.sun.com/jsf/html"
   xmlns:p="http://primefaces.prime.com.tr/ui">
<f:view contentType="text/html">
<h:head>
    <link type="text/css" rel="stylesheet"
     href="#{request.contextPath}/resources/themes/eggplant/skin.css" />

<style type="text/css">       
        .ui-widget, .ui-widget .ui-widget {
            font-size: 75% !important;
        }
        div.ss-thinpanel.ui-panel {
            padding:0px !important;
            border-top-width: 1px !important;
            border-right-width: 1px !important;
            border-bottom-width: 1px !important;
            border-left-width: 1px !important;
            margin-bottom: 1px !important;
        }
        .ss-thinpanel > div.ui-panel-titlebar {
            padding-top: 3px !important;
            padding-bottom: 2px !important;
            border:none !important;
        }
    </style>
</h:head>
<h:body>
<h:form id="frmTest">
    <h:panelGroup layout="block" style="width:800px;">
        <p:panel toggleable="true" toggleSpeed="500" collapsed="true" header="F.C. Barcelona">
            <h:outputText value="FC Barcelona is one of only three clubs never to have been relegated from La Liga and is the most successful club in Spanish football along with Real Madrid,
            having won twenty La Liga titles, a record twenty-five Spanish Cups, eight Spanish Super Cups, four Eva Duarte Cups and two League Cups.
            They are also one of the most successful clubs  in European football having won fourteen official major trophies in total,
            including ten UEFA competitions. They have won three UEFA Champions League titles, a record four UEFA Cup Winners’ Cups,
            a record three Inter-Cities Fairs Cups (the forerunner to the UEFA Europa League), three UEFA Super Cups and one FIFA Club World Cup.
            The club is also the only European side to have played continental football in every season since its inception in 1955." />
        </p:panel>
        <p:panel toggleable="true" toggleSpeed="500" collapsed="true" header="F.C. Barcelona">
            <h:outputText value="FC Barcelona is one of only three clubs never to have been relegated from La Liga and is the most successful club in Spanish football along with Real Madrid,
            having won twenty La Liga titles, a record twenty-five Spanish Cups, eight Spanish Super Cups, four Eva Duarte Cups and two League Cups.
            They are also one of the most successful clubs  in European football having won fourteen official major trophies in total,
            including ten UEFA competitions. They have won three UEFA Champions League titles, a record four UEFA Cup Winners’ Cups,
            a record three Inter-Cities Fairs Cups (the forerunner to the UEFA Europa League), three UEFA Super Cups and one FIFA Club World Cup.
            The club is also the only European side to have played continental football in every season since its inception in 1955." />
        </p:panel>
        <p:panel toggleable="true" toggleSpeed="500" collapsed="true" header="F.C. Barcelona">
            <h:outputText value="FC Barcelona is one of only three clubs never to have been relegated from La Liga and is the most successful club in Spanish football along with Real Madrid,
            having won twenty La Liga titles, a record twenty-five Spanish Cups, eight Spanish Super Cups, four Eva Duarte Cups and two League Cups.
            They are also one of the most successful clubs  in European football having won fourteen official major trophies in total,
            including ten UEFA competitions. They have won three UEFA Champions League titles, a record four UEFA Cup Winners’ Cups,
            a record three Inter-Cities Fairs Cups (the forerunner to the UEFA Europa League), three UEFA Super Cups and one FIFA Club World Cup.
            The club is also the only European side to have played continental football in every season since its inception in 1955." />
        </p:panel>
    </h:panelGroup>
    <br/>
    <h:panelGroup layout="block" style="width:800px;">
        <p:panel toggleable="true" styleClass="ss-thinpanel" toggleSpeed="500" collapsed="true" header="F.C. Barcelona">
            <h:outputText value="FC Barcelona is one of only three clubs never to have been relegated from La Liga and is the most successful club in Spanish football along with Real Madrid,
            having won twenty La Liga titles, a record twenty-five Spanish Cups, eight Spanish Super Cups, four Eva Duarte Cups and two League Cups.
            They are also one of the most successful clubs  in European football having won fourteen official major trophies in total,
            including ten UEFA competitions. They have won three UEFA Champions League titles, a record four UEFA Cup Winners’ Cups,
            a record three Inter-Cities Fairs Cups (the forerunner to the UEFA Europa League), three UEFA Super Cups and one FIFA Club World Cup.
            The club is also the only European side to have played continental football in every season since its inception in 1955." />
        </p:panel>
        <p:panel toggleable="true" styleClass="ss-thinpanel" toggleSpeed="500" collapsed="true" header="F.C. Barcelona">
            <h:outputText value="FC Barcelona is one of only three clubs never to have been relegated from La Liga and is the most successful club in Spanish football along with Real Madrid,
            having won twenty La Liga titles, a record twenty-five Spanish Cups, eight Spanish Super Cups, four Eva Duarte Cups and two League Cups.
            They are also one of the most successful clubs  in European football having won fourteen official major trophies in total,
            including ten UEFA competitions. They have won three UEFA Champions League titles, a record four UEFA Cup Winners’ Cups,
            a record three Inter-Cities Fairs Cups (the forerunner to the UEFA Europa League), three UEFA Super Cups and one FIFA Club World Cup.
            The club is also the only European side to have played continental football in every season since its inception in 1955." />
        </p:panel>
        <p:panel toggleable="true" styleClass="ss-thinpanel" toggleSpeed="500" collapsed="true" header="F.C. Barcelona">
            <h:outputText value="FC Barcelona is one of only three clubs never to have been relegated from La Liga and is the most successful club in Spanish football along with Real Madrid,
            having won twenty La Liga titles, a record twenty-five Spanish Cups, eight Spanish Super Cups, four Eva Duarte Cups and two League Cups.
            They are also one of the most successful clubs  in European football having won fourteen official major trophies in total,
            including ten UEFA competitions. They have won three UEFA Champions League titles, a record four UEFA Cup Winners’ Cups,
            a record three Inter-Cities Fairs Cups (the forerunner to the UEFA Europa League), three UEFA Super Cups and one FIFA Club World Cup.
            The club is also the only European side to have played continental football in every season since its inception in 1955." />
        </p:panel>
    </h:panelGroup>
</h:form> 
</h:body>
</f:view>
</html>

No Comments »

November 8th, 2010
1:18 pm
Header width incorrect on Primefaces scrollable table

Posted under JSF
Tags , , , , ,

If a header facet is used on a Primefaces table, the header does not allow for the scrollbars if present. the column headers do adjust for the scrollbars (although there are issues with column alignment between the headers and the data – a number of such errors have been posted to the Primefaces forum).

One workaround for this is to selectively include a CSS selector to adjust the header <div> width when the scrollbars are present.
The following selector achieves this:-

<style type=”text/css”>       

    .ss-tableheader-scrolladjust > div.ui-datatable-header {
        width:495px;
    }
</style>

The following table definition selectively includes this when enough rows are present to require scroll bars (this must be derived empirically as it depends on the height of the table, font size used etc. :-

     <h:panelGroup layout=”block” style=”width:500px;”>    
     <p:dataTable var=”car” value=”#{tableBean.carsSmall}” scrollable=”true” 
         styleClass=”#{fn:length(tableBean.carsSmall) lt 8 ? ” : ‘ss-tableheader-scrolladjust’}” height=”200″ > 
         <f:facet name=”header”>
            Ajax Sorting        
         </f:facet>
         <p:column headerText=”Model”  sortBy=”#{car.model}”>
             <h:outputText value=”#{car.model}” />
         </p:column>

         <p:column headerText=”Year”  sortBy=”#{car.year}”>
             <h:outputText value=”#{car.year}” />
         </p:column>

         <p:column headerText=”Manufacturer”  sortBy=”#{car.manufacturer}”>
             <h:outputText value=”#{car.manufacturer}” />
         </p:column>

         <p:column headerText=”Color” sortBy=”#{car.color}”>
             <h:outputText value=”#{car.color}” />
         </p:column>
     </p:dataTable>
    </h:panelGroup>

No Comments »

November 8th, 2010
12:51 pm
Setting Column Headers on a Primefaces Table

Posted under JSF
Tags , , ,

The normal way to add JSF table headers is to use a header facet :-

<p:column sortBy=”#{car.model}” >
    <f:facet name=”header”>
        <h:outputText value=”Model” />
    </f:facet>
    <h:outputText value=”#{car.model}” />
</p:column>

In Primefaces tables, this can give column width and alignment issues in some cases, so the headerText attribute of the column should be used instead :-

<p:column headerText=”Model”  sortBy=”#{car.model}”>
    <h:outputText value=”#{car.model}” />
</p:column>

No Comments »

November 8th, 2010
12:26 pm
Using JSTL Functions in JSF EL e.g. to return list size

Posted under JSF
Tags , , ,

Unfortunately some methods of backing beans, such as size() to return the number of entries in a list in a bean, are not directly callable from an EL expression as they are not exposed as standard getters. Whilst expressions on a facelets page should be used with care so as not to include business logic on the page, they are sometimes useful. One of my use cases has been to optionally add a css class into a stylclass attribute to correct the width of a table header when scrollbars are present (when enough rows are present to cause scrolling).

You can add additional properties to the beans to do this, but an easier way is often to use JSTL functions on the page. The following declaration includes the namespace for them, using prefix fn:-

<!DOCTYPE HTML>
<html xmlns=”http://www.w3c.org/1999/xhtml”
xmlns:f=”http://java.sun.com/jsf/core”
xmlns:h=”http://java.sun.com/jsf/html”
xmlns:fn=”http://java.sun.com/jsp/jstl/functions”
xmlns:p=”http://primefaces.prime.com.tr/ui”>

 

The following code fragment calls the length function to return the size of a list :-

<p:dataTable var=”car” value=”#{tableBean.carsSmall}” scrollable=”true” 
         styleClass=”#{fn:length(tableBean.carsSmall) lt 8 ? ” : ‘ss-tableheader-scrolladjust’}” height=”200″ >

 The javadoc for the complete set of jstl functions may be found here.

No Comments »

November 5th, 2010
6:34 pm
Issues with JSF h:outputStylesheet and Primefaces/jQuery skinning

Posted under JSF
Tags , , , , ,

I tried to use this whilst experimenting with dyamic style sheets, but this support post here confirms that it does not work due to an issue with the way the images are referenced.
The symptom is that you get basically correct looking layout/colours but none of the images have loaded.
The solution is to use a link tag directly e.g.:-

<link type=”text/css” rel=”stylesheet”
href=”#{request.contextPath}/resources/themes/#{themeSelectorBean.theme}/skin.css” />

Whilst on the subject of h:outputStylesheet, it should be noted that for the following example:-

<h:outputStylesheet library=”css” name=”styles.css”/>

Whilst the href of the resulting generated link tag looks like this:-

<link href=”/context-root/faces/javax.faces.resource/styles.css?ln=css”
rel=”stylesheet” type=”text/css”/>

the actual physical directory containing the style sheet in this case will be

…\WebContent\resources\css\style.css

i.e. the logical to physical mapping of the web path in this case is not straightforward and obvious. If you just create the resources folder under your project’s WebContent folder and place all your libraries as subfolders under that, it should all work correctly (the above issue with jQuery/Primefaces notwithstanding)!

No Comments »

November 5th, 2010
11:08 am
Tying Primefaces page styling to the theme

Posted under JSF
Tags , , ,

With Primefaces, rather than applying your own style for borders, headers etc. it is important where possible to tie the styling in to the theme using theme classes.
Here is an example of this from the Primefaces showcase, used to display the header for each example:-

<h1 class=”title ui-widget-header ui-corner-all”>DataTable – Pagination</h1>

This example places a border around the header according to the theme, sets the appropriate background, and adds corner rounding as per the theme.
Whilst in some cases another Primefaces component might be the right approach (in this case a panel would do it), in many cases this is undesirable and also overkill for the job. Taking our lead from the Primefaces showcase, it is clearly acceptable to use the underlying jQuery UI classes where appropriate, as I have also done here.

Here is another example page fragment which I have used to group a few controls/buttons in a box:-

<h:head>
    <style type=”text/css”>       
        .ui-widget, .ui-widget .ui-widget {
            font-size: 80% !important;
        }
        .ss-controlgroup {
            float: left;
        }

    </style>
</h:head>
<h:body>
<h:form>
<h:panelGroup layout=”block” styleClass=”ui-widget-content ui-corner-all ss-controlgroup”>

   (controls in the box go here)

</h:panelGroup>
</h:form>
</h:body>

Details of the jQuery UI, on which Primefaces is based, may be found here.

No Comments »