1
votes

I have a specific question concerning delegation an ActionListener to a composite component (jsf). I created a composite component to show (browse) and edit any personal user data (attribute "user").

    <body>
        <co:interface>
            <co:attribute name="editAction"     required="false"  targets="edit"   method-signature="java.lang.String f()"/>
            <co:attribute name="saveAction"     required="false"  targets="save"   method-signature="java.lang.String f()"/>
            <co:attribute name="cancelAction"   required="false"  targets="cancel" method-signature="java.lang.String f()"/>
            <co:attribute name="isBrowseModus"  required="true"/>
            <co:attribute name="user"           required="true"/>
            <co:attribute name="isDeveloper"    required="true"/>
            <co:actionSource name="edit"/>
            <co:actionSource name="save"/>
            <co:actionSource name="cancel"/>
        </co:interface>
............
        <p:inplace id="inpLand" editor="true" 
            toggleable="#{not cc.attrs.isBrowseModus}" 
            style="#{cc.attrs.isBrowseModus ? 'color: black' : 'color: blue'}">  
                <p:inputText value="#{cc.attrs.user.land}" label="text"/>  
        </p:inplace>  
...........
       <c:if test="#{cc.attrs.isBrowseModus}">
         <h:commandButton id="edit" value="Edit"/>
       </c:if>
........

Actually this composite component is called by a view calling myData.xhtml:

        <ui:define name="center">
            <h3>MyData Developer </h3>
            <h4>Welcomne</h4>
            <h:form id="dataForm">  
                <mc:UserData user="#{dataBean.user}" isDeveloper="#{dataBean.developer}" isBrowseModus="#{dataBean.browseModus}" cancelAction="#{dataBean.cancel}" 
saveAction="#{dataBean.save}" editAction="#{dataBean.edit}">
                    <f:actionListener for="edit" binding="#{dataBean.editActionListener}"/>
                </mc:UserData>   
            </h:form>  
        </ui:define>
    </ui:composition>

Within the composite component there is a (id = edit) and the delivered actionListener (see f:actionListener within myData) should be bound to this commandButton (id = edit). This is my understanding after reading different forum discussion and several documentations.

Unfortunately the editActionListener method isn't fire after clicking the Edit-Button and I don't know why. Surely this editActionListener method exists within the managedBean "dataBean" (myData.java):

public void editActionListener(ActionEvent ae) {
    browseModus = false;
    FacesContext.getCurrentInstance().renderResponse();
}    

What is my aim: Within that composite component the user is able by clicking the "edit" button to change any user data. I prefer using the inplace tag of PRIMEFACES. After clicking the edit button all the changeable fields should be shown in blue color.

My questions:

  1. Could anybody explain me why the bounded editActionListener method is not fired?
  2. Generally, is this the right way to set the "isBrowseModus" attribute (to false after clicking the edit button)? Or is there a more convenient way to achive this result?
  3. I'm using primefaces and first I tried to use the p:commandButton , but unfortunately it does not work. While using the p:commandButton an exception ouccured after clicking the edit button. JSF could not find the editActionListener method within my managedBean (PropertyNotFoundException)?!?!?

Any help would be appreciate. Many thanks in advance. Regards, Bodo

1

1 Answers

2
votes

According to the tag documentation, the <f:actionListener binding> must refer a concrete instance implementing the ActionListener interface, not a method expression.

All with all, your problem can be solved by providing a concrete implementation of the ActionListener interface via a getter which in turn invokes the desired action listener method.

private ActionListener editActionListener = new ActionListener() {
    @Override
    public void processAction(ActionEvent event) throws AbortProcessingException {
        DataBean.this.editActionListener(event);
    }
};

public ActionListener getEditActionListener() {
    return editActionListener;
}

public void editActionListener(ActionEvent event) {
    browseModus = false;
    FacesContext.getCurrentInstance().renderResponse();
}

This is however clumsy which indicates that you're looking for the solution in possibly the wrong direction. A simpler way is to use <cc:attribute targets="edit"> instead.

<cc:interface>
    ...
    <cc:attribute name="actionListener" targets="edit" />
</cc:interface>

which is used as

<mc:UserData ... actionListener="#{dataBean.editActionListener}" />