CommandButton don't work inside Composite

UI Components for JSF
Post Reply
User avatar
bonafe
Posts: 3
Joined: 21 Oct 2011, 20:08

21 Oct 2011, 20:16

Hello,

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

Code: Select all

<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>
				   					  		          
					<h:commandButton 
						        action = "#{cc.attrs.managedBean.toogleEditing}" 
					    	     value = "#{cc.attrs.managedBean.editing?'Back':'Edit'}" 
					        	update = "componentes"/>
					        	
					<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:

Code: Select all

<!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>
				   					  		          
					<h:commandButton 
						        action = "#{editableHTMLText.toogleEditing}" 
					    	     value = "#{editableHTMLText.editing?'Back':'Edit'}" 
					        	update = "componentes"/>
					        	
					<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:

Code: Select all

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?

cagatay.civici
Prime
Posts: 18616
Joined: 05 Jan 2009, 00:21
Location: Cybertron
Contact:

21 Oct 2011, 20:45

Try defining method attribute as an action source, e.g. method-signature.

User avatar
bonafe
Posts: 3
Joined: 21 Oct 2011, 20:08

24 Oct 2011, 17:23

Hello,

As you suggested I changed the component to call the method from a attribute.
PrimeFaces command button still don't work.
Any ideas?

Code for the changed component:

Code: Select all

<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:attribute 
			            name = "action" 
			method-signature = "java.lang.String action()"
                    required = "true"/>  
   	</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>
				   					  		          
					<h:commandButton 
						        action = "#{cc.attrs.action}" 
					    	     value = "#{cc.attrs.managedBean.editing?'Back':'Edit'}" 
					        	update = "componentes"/>
					        	
					<p:commandButton 
						        action = "#{cc.attrs.action}" 
					    	     value = "#{cc.attrs.managedBean.editing?'Back':'Edit'}" 
					        	update = "componentes"/>
				</h:panelGrid>
			</h:form>                    
      	</f:view>
   	</composite:implementation>
</ui:component>

User avatar
Oleg
Expert Member
Posts: 3805
Joined: 02 Oct 2009, 09:41
Location: Germany, Black Forest

25 Oct 2011, 09:17

I quess that's because you didn't specify "process" attribute in composite components. Try to set "process" please.
PrimeFaces Cookbook (2. edition): http://ova2.github.io/primefaces-cookbook/ Learning Angular UI Development with PrimeNG: https://github.com/ova2/angular-develop ... th-primeng Blog: https://medium.com/@OlegVaraksin

User avatar
bonafe
Posts: 3
Joined: 21 Oct 2011, 20:08

25 Oct 2011, 13:22

Sorry about the ignorance (tried to look for it elsewhere) but what is a process attribute?
Any links about it?

thanks

User avatar
Oleg
Expert Member
Posts: 3805
Joined: 02 Oct 2009, 09:41
Location: Germany, Black Forest

25 Oct 2011, 14:37

"process" attribute in p:commandButton / p:commandLink. :-) See PF Docu "Component(s) to process partially instead of whole view." Try to set process="@form" e.g. or as Id to composite component (don't forget to prepend : for NamingContainers like composite component).
PrimeFaces Cookbook (2. edition): http://ova2.github.io/primefaces-cookbook/ Learning Angular UI Development with PrimeNG: https://github.com/ova2/angular-develop ... th-primeng Blog: https://medium.com/@OlegVaraksin

mauromol
Posts: 26
Joined: 11 Apr 2014, 16:32

15 Dec 2014, 16:44

I have this exact same problem with PrimeFaces 5.1.
Inside a composite component, neither of this will perform the action or actionListener:
- p:commandButton
- p:commandButton type="button"> with a nested <p:ajax event="click">
- p:commandButton type="button" onclick="jsAction()"> together with a <p:remoteCommand name="jsAction()">
If I put the same outside of the composite it works.
If I use an <h:commandButton> with a nested <f:ajax> it works, but I lose partial processing.

Please note I *am* setting the process property and I do *not* have nested forms.
By debugging I see that the update model phase is performed correctly, while in the invoke application phase there's no queued event, and hence nothing is performed.
I can even type everything I like in action="..." and/or actionListener="..." of the p:commandButton, it doesn't complain.

I'm out of ideas on how to solve/work around this...
Last edited by mauromol on 15 Dec 2014, 16:57, edited 1 time in total.

mauromol
Posts: 26
Joined: 11 Apr 2014, 16:32

15 Dec 2014, 16:50

Oh well, after dozen minutes of trial and errors, it seems like the p:commandButton & C. need process="@this" together with other components to process in order to make actions work in this particular scenario, for instance:

<p:commandButton process="myAcutalFieldToProcess, @this" ...>

otherwise, without @this, it does not work, as I said...
:shock:

I don't think this is normal...

kukeltje
Expert Member
Posts: 9605
Joined: 17 Jun 2010, 13:34
Location: Netherlands

15 Dec 2014, 16:55

show code... please... Lots and lots of things that can be wrong afaik...

And create a new topic

mauromol
Posts: 26
Joined: 11 Apr 2014, 16:32

15 Dec 2014, 17:28

Are you the same kukeltje that contributed to jBPM? ;-)

Anyway, as far as I understand it, the original code from bonafe should allow to reproduce the issue.
I don't have time right now to produce a reproducible test case, I think you should trust me when I say that I spent hours on this and fixed by simply adding "@this" to the process attribute value of the commandButton itself and that the same set of code+facelet works when using f:ajax instead of p:ajax nested in the commandButton (without partial processing, of course).

I didn't open a new thread because my problem with PF 5.1 is the exact same one described by bonafe: a commandButton that works when put outside a composite component does not invoke its action or actionListner once put inside a composite component. No errors by Mojarra, neither by PF, even when run in Development mode. You can even put whatever you want inside action="..." without any complaint being produced, like this:
<p:commandButton action="#{whatever-you-want}" />

Proof-of-concept:

Code: Select all

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://xmlns.jcp.org/jsf/html"
	xmlns:f="http://xmlns.jcp.org/jsf/core"
	xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
	xmlns:p="http://primefaces.org/ui"
	xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
	xmlns:jsf="http://xmlns.jcp.org/jsf"
	xmlns:cc="http://xmlns.jcp.org/jsf/composite"
	xmlns:c="http://java.sun.com/jsp/jstl/core">

<cc:interface>
	<cc:attribute name="value" required="true" />
	<cc:attribute name="focusFor" required="false" />
	<cc:attribute name="addButtonTitle" required="false" />
	<cc:attribute name="disabled" required="false" default="false" />
	<cc:attribute name="readOnly" required="false" default="false" />
</cc:interface>

<cc:implementation>

	<ui:param name="bean" value="#{cc.attrs.value}"></ui:param>

	<div id="#{cc.clientId}">
		<h:panelGroup id="subform">
			<cc:insertChildren />
		</h:panelGroup>
		<f:phaseListener binding="#{bean.resetJustAddedListener}" />
		<c:if test="#{not empty cc.attrs.focusFor}">
			<p:focus for="#{cc.attrs.focusFor}" rendered="#{bean.justAdded}" />
		</c:if>
		<!-- 
			DO NOT remove @this from process attribute value
		 -->
		<p:commandButton ajax="true" process="subform @this" update="#{cc.parent.clientId}"
			action="#{bean.addObject}" value="Aggiungi" title="#{cc.attrs.addButtonTitle}" />
	</div>
</cc:implementation>

</html>
In the including facelet:

Code: Select all

<myNS:myCompositeComponent
	value="#{bean.myCcBean}"
	focusFor=":form:textField"
	addButtonTitle="Bla bla">
	<p:outputLabel value="Enter text:" for="textField">
		<p:inputText id="textField"
			value="#{bean.myCcBean.objectToAdd.stringField}"
			title="Foo" />
	</p:outputLabel>
	<p:message for="textField" />
</myNS:myCompositeComponent>
Backing bean (in Groovy):

Code: Select all

class MyCcBean  {

	Object objectToAdd

	Closure emptyObjectFactory
	Closure addObjectAction

	boolean justAdded

	void init() {
		objectToAdd = emptyObjectFactory()
	}

	void addObject() {
		// perform the add action
		addObjectAction(objectToAdd)
		// reset the input form
		objectToAdd = emptyObjectFactory()
		// track that an object has just been added
		justAdded = true
	}

	PhaseListener resetJustAddedListener = [
		getPhaseId: {PhaseId.RENDER_RESPONSE},
		beforePhase: {},
		afterPhase: { justAdded = false }
	] as PhaseListener
}
The backing bean logic should be irrelevant. The original problem is that MyCcBean.addObject() is not invoked.

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 58 guests