11
votes

In the code bellow the jsf html commandButton action is called perfectly. But primefaces commandButton action is not called.

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

    <composite:interface>
        <composite:attribute 
            name="managedBean"          
            type="java.lang.Object"
            required="true">                    
        </composite:attribute>
    </composite:interface>

    <composite:implementation>
        <f:view contentType="text/html"> 
            <h:form id="componentes">  
                <h:panelGrid columns="3">
                    <h:panelGroup>              
                        <h:outputText 
                              escape = "false" 
                               value = "#{cc.attrs.managedBean['value']}"       
                            rendered = "#{!cc.attrs.managedBean['editing']}"/> 
                        <p:editor 
                            widgetVar = "editor" 
                                value = "#{cc.attrs.managedBean.value}" 
                             rendered = "#{cc.attrs.managedBean.editing}"/>
                    </h:panelGroup>
                    <!-- ACTION IS CALLED -->                                 
                    <h:commandButton 
                                action = "#{cc.attrs.managedBean.toogleEditing}" 
                                 value = "#{cc.attrs.managedBean.editing?'Back':'Edit'}" 
                                update = "componentes"/>

                                    <!-- ACTION IS NOT CALLED -->           
                    <p:commandButton 
                                action = "#{cc.attrs.managedBean.toogleEditing}" 
                                 value = "#{cc.attrs.managedBean.editing?'Back':'Edit'}" 
                                update = "componentes"/>
                </h:panelGrid>
            </h:form>                    
        </f:view>
    </composite:implementation>
</ui:component>

If place the same code is outside a composite (a normal xhtml page), both work fine:

<!DOCTYPE html 
     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html 
    xml:lang="pt" 
        lang="pt"
       xmlns="http://www.w3.org/1999/xhtml" 
     xmlns:f="http://java.sun.com/jsf/core"
     xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
     xmlns:p="http://primefaces.prime.com.tr/ui">

    <h:head id="head">
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Item de Texto</title>
    </h:head>
    <h:body id="body">          
        <f:view contentType="text/html"> 
            <h:form id="componentes">  
                <h:panelGrid columns="3">
                    <h:panelGroup>              
                        <h:outputText 
                              escape = "false" 
                               value = "#{editableHTMLText.value}" 
                            rendered = "#{!editableHTMLText.editing}"/>
                        <p:editor 
                            widgetVar = "editor" 
                                value = "#{editableHTMLText.value}" 
                             rendered = "#{editableHTMLText.editing}"/>
                    </h:panelGroup>

                                    <!-- ACTION IS CALLED -->                         
                    <h:commandButton 
                                action = "#{editableHTMLText.toogleEditing}" 
                                 value = "#{editableHTMLText.editing?'Back':'Edit'}" 
                                update = "componentes"/>

                                    <!-- ACTION IS CALLED -->
                    <p:commandButton 
                                action = "#{editableHTMLText.toogleEditing}" 
                                 value = "#{editableHTMLText.editing?'Back':'Edit'}" 
                                update = "componentes"/>
                </h:panelGrid>
            </h:form>                    
        </f:view>
    </h:body>
</html>

This is the bean code:

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;


@ManagedBean
@SessionScoped
public class EditableHTMLText implements Serializable{

    /**
     * 
     */
    private static final long   serialVersionUID    = 8439126615761864409L;

    private String              value               = "Test<br>of<br>HTML<br>text<br><b>ITEM</b><br>";
    private boolean             editing             = false;


    public void toogleEditing(){

        this.setEditing(!this.isEditing());
        System.out.println("Editing State: " + this.editing);
    }


    public String getValue(){

        return value;
    }


    public void setValue(String value){

        this.value = value;
    }


    public boolean isEditing(){

        return editing;
    }


    public void setEditing(boolean editing){

        this.editing = editing;
    }

}

Any suggestions?

8

8 Answers

20
votes

Today I hit this exact same problem with PrimeFaces 5.1. In my case I had no nested forms and I was already setting the process attribute on the p:commandButton with the form elements I wanted to be processed. However this didn't work yet.

The "solution" was to add @this to the list of components to process, like this:

<p:commandButton process="myFormField1 myFormField2 @this">

Without @this (which is not usually needed, since the button itself shouldn't need to be processed/validated) I found no way to make any of these to work inside a composite:

  • <p:commandButton action="#{bean.myAction}"...>
  • <p:commandButton type="button"> with nested <p:ajax event="click" action="#{bean.myAction}"...>
  • <p:commandButton type="button" onclick="myAction()"> with associated <p:remoteCommand name="myAction" action="#{bean.myAction}">

By debugging the application, I saw that the validation and update model phases were correctly executed, but then in the invoke application phase no queued event was present and hence no action was performed. Actually, I could specify anything I liked inside the action and actionListener attribute values of <p:commandButton> without having either PrimeFaces or JSF complain in any way.

These, instead, do work as they should, but you don't have partial processing in place, so they may not be a viable solution:

  • <p:commandButton action="#{bean.myAction}" ajax="false"...>
  • <p:commandButton type="button"...> with nested <f:ajax event="click" action="#{bean.myAction}"...>

It must be a PrimeFaces bug.

6
votes

When you used the composite component, was it already placed in a h:form tag? When you have nested forms, command button action isn't triggered.

Another issue can be the ajax parts that you are trying. Primefaces button has the update attribute, but the standard JSF one does not have that. It will do always a complete refresh of the page (except when nested in or f:ajax tag is used inside it)

1
votes

You can try to insert ajax="false" attribute in p:commandButton.

1
votes

I had also problems with non-triggering commandButtons. In my case ajax and non-ajax reqeuests didn't work. 1. as described above - be sure to delete all form's in form's. easy done with composite usage. 2. if you have several buttons, try to use the flag "process". Helped in my case.

<p:commandButton id="submitButton" value="Submit" type="submit" 
    actionListener="#{bean.save}"
    update="message"
    process="txtComment, @this"
    icon="ui-icon-disk"/>

process="txtComment, @this" executes the setter method of inputText with id txtComment and the commandButton method.

0
votes

I also hit this problem and tested out your codes, it seems that primefaces is unable to warn you validation errors in the same "xhtml" but in other panelGrids, you may need a parent panelGrid to properly encapsulate all your form's grids.

If you fill up your entire form completely, you will see that your primefaces commandButton action is called upon, otherwise it would silently "digest" the validation errors you may have.

0
votes

To add to the above answers, for completeness.

One of the issue not covered in the above answers is the missing Targets attribute in composite:interface

From the docs of JSF

targets attribute: If this element has a method-signature attribute, the value of the targets attribute must be interpreted as a space (not tab) separated list of client ids (relative to the top level component) of components within the <composite:implementation> section. Space is used as the delimiter for compatibility with the IDREFS and NMTOKENS data types from the XML Schema. Each entry in the list must be interpreted as the id of an inner component to which the MethodExpression from the composite component tag in the using page must be applied. If this element has a method-signature attribute, but no targets attribute, the value of the name attribute is used as the single entry in the list. If the value of the name attribute is not one of the special values listed in the description of the name attribute, targets (or its derived value) need not correspond to the id of an inner component.

<cc:interface>
    <cc:attribute name="value" />
    <cc:attribute name="action" targets="buttonId" />
    <cc:attribute name="actionListener" targets="buttonId" />
</cc:interface>
<cc:implementation>
    <p:commandButton id="buttonId" value="#{cc.attrs.value}" />
</cc:implementation>

@source: https://stackoverflow.com/a/19680483/1850844

0
votes

probably you have some elements in your page, com REQUIRED="TRUE" is conflicting

-1
votes

I Found a workaround for this Problem

<composite:implementation>
 <p:commandButton onclick="JS_call_to<p:remoteCommand>" />
</composite:implementation>

Inside your mainpage define with
<p:remoteCommand action="managedBean.call_function()" update="..." />

I have made a Gmap Call with this from a Composite-Component to my Mainpage