- 

Available since OmniFaces 2.0

The <o:moveComponent> component is a utility component via which components, facets and behaviors can be moved at runtime to a target component in various ways. This allows for simple programmatic composition of components using a declarative page author centric approach.

The destination of a move operation is specified in terms of a location that's relative to a given target component. The following shows a list of supported destinations:

  • BEFORE - Component is moved right before target component, i.e. as a sibling with an index that's 1 position lower.
  • ADD_FIRST - Component is added as the first child of the target component, any other children will have their index increased by 1.
  • ADD_LAST - Component is added as the last child of the target component, any other children will stay at their original location.
  • FACET - Component will be moved to the facet section of the target component under the name denoted by "facet".
  • BEHAVIOR - A Behavior will be moved to the behavior section of the target component.
  • AFTER - Component is moved right after target component, i.e. as a sibling with an index that's 1 position higher.
Demo

Showing number of search results in PrimeFaces table

The PrimeFaces data table component is notoriously difficult to modify when it comes to the build-in filter/search capabilities. Required components with fixed IDs ("globalFilter") and the fact that filtering is applied in the render stage are among the things that make this surprisingly difficult in practice.

With the help of the o:moveComponent the required modification actions can be packed up in a Facelets tag file for reuse. The following shows an example:


 

John Peterson 32
Linda Harrison 33
Akira Yamada 18
Fangni Chen 39

So what's going on here? The demo:globalSearch tag (see second tab in the source code section below) contains 3 instances of the o:moveComponent.

1. Moving a script to reside after the table

The first moveComponent instance has a JavaScript surrounded by a named panel group as its children. These components are moved in the tree to sit right after the table component. This script takes the number of elements that appear in the so-called filtered collection and updates another panel group with that number.

The script needs to be placed AFTER the table component, because the number we need is only available when the table is actually rendered, so it's only available to components (and EL expressions within those) that are rendered after the table is rendered. This somewhat defeats the purpose of the phases in Faces (an important reason for which is to prevent just this location dependency), but with the o:moveComponent we can hide this somewhat nasty detail for the tag user.

2. Moving an AJAX event listener into the table

The second moveComponent instance has an AJAX event listener as its child. The event listener makes sure the JavaScript that we defined above is updated after each filtering operation.

An AJAX event listener is not a component but a behavior. It therefore needs some extra handling. (among others to fool it that it's temporarily a child of the moveComponent which does not have the events a behavior can be checking for) It's moved to the special behavior section components have.

3. Moving a component into the facet section of the table

The third moveComponent instance has a placeholder component with the fixed ID 'globalFilter' as its child. This component is used by PrimeFaces to read the input used by the filtering operation from.

This placeholder component is needed for this example, since we wanted to have the real input component just above the table, not inside the table. The standard PrimeFaces approach with the facet tightly couples the location of the input component, which we here thus decouple. The real input component updates the placecholder using its onkeyup attribute.

Demo source code
<h3>Showing number of search results in PrimeFaces table</h3>

<p>
The PrimeFaces data table component is notoriously difficult to modify when it comes to the build-in filter/search capabilities.
Required components with fixed IDs ("globalFilter") and the fact that filtering is applied in the render stage are among the
things that make this surprisingly difficult in practice. 
</p>

<p>
With the help of the o:moveComponent the required modification actions can be packed up in a Facelets tag file for reuse.
The following shows an example: 
</p>

<hr/>

<demo:globalSearch forx="myTable"/> <br/><br/>


<h:form id="myForm">
    <p:dataTable id="myTable" value="#{myTableBacking.users}" var="user" filteredValue="#{myTableBacking.filteredUsers}" widgetVar="myTableVar">
        <p:column filterBy="#{user.firstName}" filterMatchMode="contains">  
            #{user.firstName}
        </p:column>
    
        <p:column filterBy="#{user.lastName}" filterMatchMode="contains">  
            #{user.lastName}
        </p:column>
    
        <p:column filterBy="#{user.age}" filterMatchMode="contains"> 
            #{user.age}
        </p:column>
    </p:dataTable>
</h:form>
<hr/>

<p>
So what's going on here? The <b>demo:globalSearch</b> tag <i>(see second tab in the source code section below)</i> contains 3 instances
of the o:moveComponent.
</p>


<h4>1. Moving a script to reside after the table</h4>

<p>
The first moveComponent instance has a JavaScript surrounded by a named panel group as its children. These components are moved in the tree
to sit right after the table component. This script takes the number of elements that appear in the so-called filtered collection and updates
another panel group with that number.<br/> <br/> 
The script needs to be placed AFTER the table component, because the number we need is only available
when the table is actually rendered, so it's only available to components (and EL expressions within those) that are rendered after the table
is rendered. This somewhat defeats the purpose of the phases in Faces (an important reason for which is to prevent just this location dependency),
but with the o:moveComponent we can hide this somewhat nasty detail for the tag user.
</p>

<h4>2. Moving an AJAX event listener into the table</h4>

<p>
The second moveComponent instance has an AJAX event listener as its child. The event listener makes sure the JavaScript that we defined above is
updated after each filtering operation.<br/> <br/> 

An AJAX event listener is not a component but a behavior. It therefore  needs some extra handling. <i>(among others to fool it that it's temporarily
a child of the moveComponent which does not have the events a behavior can be checking for)</i> It's moved to the special behavior section 
components have.
</p>

<h4>3. Moving a component into the facet section of the table</h4> 

<p>
The third moveComponent instance has a placeholder component with the fixed ID 'globalFilter' as its child. This component is used by PrimeFaces
to read the input used by the filtering operation from.<br/> <br/> 

This placeholder component is needed for this example, since we wanted to have the real input component just above the table, not inside the table.
The standard PrimeFaces approach with the facet tightly couples the location of the input component, which we here thus decouple. The real input
component updates the placecholder using its <code>onkeyup</code> attribute.
</p>