Book Image

Primefaces Cookbook Second Edition

Book Image

Primefaces Cookbook Second Edition

Overview of this book

Table of Contents (20 chapters)
PrimeFaces Cookbook Second Edition
Credits
Foreword
Foreword
About the Authors
About the Reviewers
www.PacktPub.com
Preface
Index

PrimeFaces selectors


PrimeFaces integrates the jQuery Selector API (http://api.jquery.com/category/selectors) with the JSF component-referencing model. Partial processing and updating of the JSF components can be done using the jQuery Selector API instead of a regular server-side approach with findComponent(). This feature is called the PrimeFaces Selector (PFS) API. PFS provides an alternative, flexible approach to reference components to be processed or updated partially. PFS is a client-side part of the PrimeFaces SEF, which provides both server-side and client-side extensions to make it easier to reference components.

In comparison with regular referencing, there is less CPU server load because the JSF component tree is not traversed on the server side in order to find client IDs. PFS is implemented on the client side by looking at the DOM tree. Another advantage is avoiding container limitations, and thus the cannot find component exception—since the component we were looking for was in a different naming container.

The essential advantage of this feature, however, is speed. If we reference a component by an ID, jQuery uses document.getElementById(), a native browser call behind the scene. This is a very fast call, much faster than that on the server side with findComponent(). The second use case, where selectors are faster, is when we have a lot of components with the rendered attributes set to true or false. The JSF component tree is very big in this case, and the findComponent() call is time consuming. On the client side, only the visible part of the component tree is rendered as markup. The DOM is smaller than the component tree and its selectors work faster.

In this recipe, we will learn PFS in detail. PFS is recognized when we use @(...) in the process or update attribute of AJAX-ified components. We will use this syntax in four command buttons to reference the parts of the page we are interested in.

How to do it…

The following code snippet contains two p:panel tags with the input, select, and checkbox components respectively. The first p:commandButton component processes/updates all components in the form(s). The second one processes / updates all panels. The third one processes input, but not select components, and updates all panels. The last button only processes the checkbox components in the second panel and updates the entire panel.

<p:messages id="messages" autoUpdate="true"/>

<p:panel id="panel1" header="First panel">
  <h:panelGrid columns="2">
    <p:outputLabel for="name" value="Name"/>
      <p:inputText id="name" required="true"/>

    <p:outputLabel for="food" value="Favorite food"/>
    <h:selectOneMenu id="food" required="true">
    ...
    </h:selectOneMenu>

    <p:outputLabel for="married" value="Married?"/>
    <p:selectBooleanCheckbox id="married" required="true"
      label="Married?">
      <f:validator validatorId="org.primefaces.cookbook.
        validator.RequiredCheckboxValidator"/>
    </p:selectBooleanCheckbox>
  </h:panelGrid>
</p:panel>

<p:panel id="panel2" header="Second panel">
  <h:panelGrid columns="2">
    <p:outputLabel for="address" value="Address"/>
    <p:inputText id="address" required="true"/>

    <p:outputLabel for="pet" value="Favorite pet"/>
    <h:selectOneMenu id="pet" required="true">
    ...
    </h:selectOneMenu>

    <p:outputLabel for="gender" value="Male?"/>
    <p:selectBooleanCheckbox id="gender" required="true"
    label="Male?">
    <f:validator validatorId="org.primefaces.cookbook.
    validator.RequiredCheckboxValidator"/>
    </p:selectBooleanCheckbox>
  </h:panelGrid>
</p:panel>

<h:panelGrid columns="5" style="margin-top:20px;">
  <p:commandButton process="@(form)" update="@(form)"
    value="Process and update all in form"/>

  <p:commandButton process="@(.ui-panel)" update="@(.ui-panel)"
    value="Process and update all panels"/>

  <p:commandButton process="@(.ui-panel :input:not(select))"
    update="@(.ui-panel)"
     value="Process inputs except selects in all panels"/>

  <p:commandButton process="@(#panel2 :checkbox)"
    update="@(#panel2)"
    value="Process checkboxes in second panel"/>
</h:panelGrid>

Note

In terms of jQuery selectors, regular input field, selection, and checkbox controls are all inputs. They can be selected by the :input selector.

The following screenshot shows what happens when the third button is pushed. The p:inputText and p:selectBooleanCheckbox components are marked as invalid. The h:selectOneMenu component is not marked as invalid although no value was selected by the user.

How it works…

The first selector from the @(form) first button selects all forms on the page. The second selector, @(.ui-panel), selects all panels on the page as every main container of PrimeFaces' p:panel component has this style class. Component style classes are usually documented in the Skinning section in PrimeFaces User's Guide (http://www.primefaces.org/documentation.html). The third selector, @(.ui-panel :input:not(select)), only selects p:inputText and p:selectBooleanCheckbox within p:panel. This is why h:selectOneMenu was not marked as invalid in the preceding screenshot. The validation of this component was skipped because it renders itself as an HTML select element. The last selector variant, @(#panel2 :checkbox), intends to select p:selectBooleanCheckbox in the second panel only.

Tip

In general, it is recommended that you use Firebug (https://getfirebug.com) or a similar browser add-on to explore the generated HTML structure when using jQuery selectors.

A common use case is skipping validation for the hidden fields. Developers often hide some form components dynamically with JavaScript. Hidden components get validated anyway, and the form validation can fail if the fields are required or have other validation constraints. The first solution would be to disable the components (in addition to hiding them). The values of disabled fields are not sent to the server. The second solution would be to use jQuery's :visible selector in the process attribute of a command component that submits the form.

There's more…

PFS can be combined with regular component referencing as well, for example, update="compId1 :form:compId2 @(.ui-tabs :input)".

The PrimeFaces Cookbook Showcase application

This recipe is available in the demo web application on GitHub (https://github.com/ova2/primefaces-cookbook/tree/second-edition). Clone the project if you have not done it yet, explore the project structure, and build and deploy the WAR file on application servers compatible with Servlet 3.x, such as JBoss WildFly and Apache TomEE.

The showcase for the recipe is available at http://localhost:8080/pf-cookbook/views/chapter1/pfs.jsf.