JSF2.0 Composite Component actionListener
Asked Answered
T

2

5

I am in need of some assistance in getting my Composite Component to behave. I am still learning the ropes in JSF, so please excuse any ignorance that might be displayed in this post.

So, I am working with JSF 2.0 and decided to build a composite component to make this particular code snippet reusable. The component displays everything perfectly, but will not behave at all when trying to add the actionListener.

Here is the code for my component

<ui:composition
    xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:h="http://java.sun.com/jsf/html"  
    xmlns:ui="http://java.sun.com/jsf/facelets" 
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:composite="http://java.sun.com/jsf/composite">

    <composite:interface displayName="columnUpdate">
        <composite:attribute name="id" 
            required="true" 
            displayName="id"
            shortDescription="Id to apply to this control and its child components">
        </composite:attribute>
        <composite:attribute 
            name="value" 
            displayName="value"
            required="true" 
            shortDescription="Field that will hold the new updated value.">
        </composite:attribute>

        <composite:attribute 
            name="columnName" 
            displayName="columnName"
            required="true" 
            shortDescription="Value that will be applied as the column header">
        </composite:attribute>
        <composite:attribute 
            name="text"
            displayName="text"
            shortDescription="Text to be displayed above the field">
        </composite:attribute>

        <composite:actionSource name="actionEvent" targets="saveEvent"></composite:actionSource>
    </composite:interface>

    <composite:implementation>
        <h:outputLabel value="#{cc.attrs.columnName}" onclick="showWindow('#{cc.attrs.id}')"></h:outputLabel>

        <div id="#{cc.attrs.id}" class="ccColumnUpdate">
        <div id="windowClose" onclick="closeWindow('#{cc.attrs.id}');" style="top: -10px;" title="Close this window">CLOSE</div>
            <div>
                <h:outputLabel id="lblTitle" value="#{cc.attrs.text}"></h:outputLabel>
            </div>
            <div>
                <h:inputText id="txtValue" value="#{cc.attrs.value}"></h:inputText>
            </div>
            <div style="text-align:right;">
                <h:commandButton id="saveEvent" value="Save"></h:commandButton>
            </div>
        </div>
    </composite:implementation>
</ui:composition>

Here is the code in my page that uses the component:

<al:columnUpdate id="cuExpenseAmount" value="#{expense.columnValue}" columnName="Expense Amount" text="Set Expense Amount to:">
  <f:actionListener for="actionEvent" binding="#{expense.updateColumnValue}">
    <f:ajax execute="@form"></f:ajax>
  </f:actionListener>
</al:columnUpdate>

and here is my code on the Backing Bean:

public void updateColumnValue(ActionEvent event) throws ParseException{
    //Got HERE

}

I am not receiving any errors or hit any breakpoints I set on the backing bean. Any help, or pointers in the right direction would be appreciated.

Regards,

Mike

Tergal answered 7/12, 2011 at 21:51 Comment(0)
T
9

I found the answer after playing around a little bit and more searching.

Changes to the composite component: FROM:

<composite:actionSource name="actionEvent" targets="saveEvent"></composite:actionSource> 

<h:commandButton id="saveEvent" value="Save"></h:commandButton>  

TO:

<composite:attribute name="registerButtonActionListener" method-signature="void actionListener(javax.faces.event.ActionEvent)" />

<h:commandButton id="saveEvent" value="Save" actionListener="#{cc.attrs.registerButtonActionListener}">
                    <f:ajax execute="@this" event="click"></f:ajax>
                </h:commandButton>

Changes to the page using the composite component:

<al:columnUpdate id="cuExpenseAmount" value="#{expense.columnValue}" registerButtonActionListener="#{expense.updateColumnValue}" columnName="Expense Amount">
                            </al:columnUpdate>

The big change was defining the method signature in the composite attribute.

Regards,

Mike

Tergal answered 8/12, 2011 at 15:1 Comment(0)
H
0

I found an alternative solution to yours. A drawback of your solution is that you can only register one listener: the actionListener attribute can only point to one method.

The way to add listeners is as follows (you almost had it right in the first piece of code you wrote):

<al:columnUpdate id="cuExpenseAmount" value="#{expense.columnValue}" columnName="Expense Amount" text="Set Expense Amount to:">
<f:actionListener for="actionEvent" binding="#{expense.updateColumnValue(ActionEvent)}">
    <f:ajax execute="@form"></f:ajax>
</f:actionListener> </al:columnUpdate>

Notice how the method pointed to by binding takes an ActionEvent parameter. This is a requirement of using <f:actionlistener/>.

Using this method, multiple listeners can be registered to the action source made available by the composite component.

Hesperidium answered 9/7, 2012 at 10:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.