Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PrimeFaces CommandButton Action not called inside Composite

Tags:

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?

like image 611
Fernando Bonafé Avatar asked Oct 21 '11 18:10

Fernando Bonafé


2 Answers

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.

like image 113
Mauro Molinari Avatar answered Jan 02 '23 19:01

Mauro Molinari


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)

like image 34
Rudy De Busscher Avatar answered Jan 02 '23 20:01

Rudy De Busscher