dataTable commandLink for row actions

UI Components for JSF
cbmyers
Posts: 53
Joined: 20 Oct 2010, 14:56

29 Oct 2010, 13:01

Hi,

This may be a newbe question, but here goes.

I am trying to add commandlinks, (or better yet) menubutton, (or even better yet) a context menu for per row actions in a dataTable.

I have read about the future work that is going to happen with dataTable and contextmenu. That sounds awesome.

I tried the menu button but, as noted else were in the forums, when ever you click on the menubutton, the menu that opens is for the last row. (having done some research, it seems h:menubutton has the same problem and it was attributed to the fact that the id of the menubutton was the same for each row. i don't know if that is the problem here or not, but i though i would share just in case.)

The menuButton set up works as expected (except that you can only perform the actions on the last row).

So, i have switched to commandLinks as suggested in the forum. The problem is whenever i click on the link i am getting null pointer errors.

here is the error messages:

javax.faces.FacesException
at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:82)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:308)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.NullPointerException
at java.lang.reflect.Array.newArray(Native Method)
at java.lang.reflect.Array.newInstance(Array.java:52)
at org.primefaces.component.datatable.DataHelper.decodeMultipleSelection(DataHelper.java:246)
at org.primefaces.component.datatable.DataHelper.decodeSelection(DataHelper.java:197)
at org.primefaces.component.datatable.DataTableRenderer.decode(DataTableRenderer.java:57)
at javax.faces.component.UIComponentBase.decode(UIComponentBase.java:791)
at javax.faces.component.UIData.processDecodes(UIData.java:981)
at javax.faces.component.UIForm.processDecodes(UIForm.java:212)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1043)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1043)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1043)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1043)
at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:920)
at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:74)
... 15 more


and here is the command link code:

<p:commandLink action="#{listFacilities.deleteFacility}" update="facilityList">
<h:outputText value="Delete" />
<f:param name="facilityId" value="#{facility.facilityId}"/></p:commandLink>

and the java code:

public String deleteFacility(ActionEvent actionEvent) throws NumberFormatException, GuardianStatException {
// public String deleteFacility() throws NumberFormatException, GuardianStatException {
System.out.println("In delete facility");

// UIParameter facilityIdComponent = (UIParameter) actionEvent.getComponent().findComponent("facilityId");
// long facilityId2 = Long.parseLong(facilityIdComponent.getValue().toString());

String facilityId = facesContext.getExternalContext().getRequestParameterMap().get("facilityId");
System.out.println("Facility ID: " + facilityId);
// System.out.println("Facility ID2: " + facilityId2);

FacilityHelper.deleteFacility(FacilityHelper.getFacility(Long.parseLong(facilityId)));

getFacilityListFromDatabase();

return null;
}

the system.out.println("in delete facility") never happens.

as you can see from the commented out code, i have tried with and without the ActionEvent parameter. I am at a lost as to why this is happening and have not been able to find any other forum (or web) help. This could be missing something completely obvious as I am a struts guy and am very new to JSF.

Thanks for any help.
Last edited by cbmyers on 01 Nov 2010, 16:56, edited 1 time in total.
- Chris
PrimeFaces 3.0M1
Eclipse Indigo (with Tomcat 7.0.14)
Java 1.6
JSF 2.0 (Mojarra 2.0.4)
hibernate 3.5.5

cbmyers
Posts: 53
Joined: 20 Oct 2010, 14:56

01 Nov 2010, 14:14

a little more info:

after looking at the generated html, The ids of the commandlinks are not the same, so that is not the problem.

i have pasted the generated html of the links below.

Code: Select all

row 1

<td><span><a id="j_idt40:facilityList:0:j_idt76" href="javascript:void(0);" onclick="PrimeFaces.ajax.AjaxRequest('/GuardianStat/admin/listFacilities.xhtml',{formId:'j_idt40',async:false,global:true,source:'j_idt40:facilityList:0:j_idt76',process:'@all'},{'facilityId':'3'});">Modify,</a> 
<a id="j_idt40:facilityList:0:j_idt79" href="javascript:void(0);" onclick="PrimeFaces.ajax.AjaxRequest('/GuardianStat/admin/listFacilities.xhtml',{formId:'j_idt40',async:false,global:true,source:'j_idt40:facilityList:0:j_idt79',process:'@all',update:'j_idt40:facilityList:0'},{'facilityId':'3'});">Delete</a></span></td>

row 2

<td><span><a id="j_idt40:facilityList:1:j_idt76" href="javascript:void(0);" onclick="PrimeFaces.ajax.AjaxRequest('/GuardianStat/admin/listFacilities.xhtml',{formId:'j_idt40',async:false,global:true,source:'j_idt40:facilityList:1:j_idt76',process:'@all'},{'facilityId':'1'});">Modify,</a> 
<a id="j_idt40:facilityList:1:j_idt79" href="javascript:void(0);" onclick="PrimeFaces.ajax.AjaxRequest('/GuardianStat/admin/listFacilities.xhtml',{formId:'j_idt40',async:false,global:true,source:'j_idt40:facilityList:1:j_idt79',process:'@all',update:'j_idt40:facilityList:1'},{'facilityId':'1'});">Delete</a></span></td>

row 3

<td><span><a id="j_idt40:facilityList:2:j_idt76" href="javascript:void(0);" onclick="PrimeFaces.ajax.AjaxRequest('/GuardianStat/admin/listFacilities.xhtml',{formId:'j_idt40',async:false,global:true,source:'j_idt40:facilityList:2:j_idt76',process:'@all'},{'facilityId':'2'});">Modify,</a> 
<a id="j_idt40:facilityList:2:j_idt79" href="javascript:void(0);" onclick="PrimeFaces.ajax.AjaxRequest('/GuardianStat/admin/listFacilities.xhtml',{formId:'j_idt40',async:false,global:true,source:'j_idt40:facilityList:2:j_idt79',process:'@all',update:'j_idt40:facilityList:2'},{'facilityId':'2'});">Delete</a></span></td>
Thanks
- Chris
PrimeFaces 3.0M1
Eclipse Indigo (with Tomcat 7.0.14)
Java 1.6
JSF 2.0 (Mojarra 2.0.4)
hibernate 3.5.5

cbmyers
Posts: 53
Joined: 20 Oct 2010, 14:56

01 Nov 2010, 14:23

using firebug to see the request and responce i see this response:

Code: Select all

<?xml version='1.0' encoding='UTF-8'?>
<partial-response><error><error-name>class java.lang.NullPointerException</error-name><error-message><![CDATA[]]></error-message></error><extension primefacesCallbackParam="validationFailed">{"validationFailed":false}</extension></partial-response>
I am not doing any implicit validation so i am not sure what validation is failing.

thanks again,
- Chris
PrimeFaces 3.0M1
Eclipse Indigo (with Tomcat 7.0.14)
Java 1.6
JSF 2.0 (Mojarra 2.0.4)
hibernate 3.5.5

cbmyers
Posts: 53
Joined: 20 Oct 2010, 14:56

01 Nov 2010, 18:16

Here is the complete listing of the managed bean and the xhtml file. Hopefully this will help.

managed bean:

Code: Select all

package com.protech.beans.managed;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.component.UIParameter;
import javax.faces.event.ActionEvent;

import org.primefaces.event.RowEditEvent;

import com.protech.beans.Facility;
import com.protech.exception.GuardianStatException;
import com.protech.helpers.FacilityHelper;
import com.protech.util.GuardianStatConstants;

@ManagedBean
public class ListFacilities extends BaseBean {

	private static final long serialVersionUID = 1L;
	
	private List<Facility> facilities;
	
	private Facility selectedFacility;
	
	private boolean displayPage = true;
	
	public ListFacilities() throws GuardianStatException {
		getFacilityListFromDatabase();
	}
	
	public List<Facility> getFacilities() {
		return facilities;
	}
	
	public Facility getSelectedFacility() {
		return selectedFacility;
	}
	
	public void setSelectedFacility(Facility selectedFacility) {
		this.selectedFacility = selectedFacility;
	}
	
	@PostConstruct
	public void init() {
		if (!guardianStatSession.getLoggedInUserRoles().contains(GuardianStatConstants.ROLE_ADMIN)) {
			displayPage = false;
		}
	}
	
	private void getFacilityListFromDatabase() throws GuardianStatException {
		facilities = FacilityHelper.getFacilities();
	}
	
	public void rowEdit(RowEditEvent rowEditEvent){
        try {
            Facility facility = (Facility)rowEditEvent.getObject();
            
            FacilityHelper.saveOrUpdateFacility(facility);
            
        } catch (Exception e) {
            facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "ERROR", e.toString()));
        }
    }
	
	public String deleteFacility(ActionEvent actionEvent) throws NumberFormatException, GuardianStatException {
		System.out.println("In delete facility");
		
		UIParameter facilityIdComponent = (UIParameter) actionEvent.getComponent().findComponent("facilityId");
		long facilityId = Long.parseLong(facilityIdComponent.getValue().toString());
		
		System.out.println("Facility ID: " + facilityId);
		
		FacilityHelper.deleteFacility(FacilityHelper.getFacility(facilityId));
		
		getFacilityListFromDatabase();
		
		return null;
	}		
	
	public void modifyFacility() {

		String facilityId = facesContext.getExternalContext().getRequestParameterMap().get("facilityId");
		System.out.println("Facility ID (passed): " + facilityId);

	}

	public boolean getDisplayPage() {
		return displayPage;
	}

	public void setDisplayPage(boolean displayPage) {
		this.displayPage = displayPage;
	}
}
xhtml:

Code: Select all

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

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

<ui:composition template="/WEB-INF/templates/GuardianStatTemplate.xhtml">

	<ui:define name="content">

	<br/>
	    <h:form>

				<p:button value="Add Facility" image="icoBldg" outcome="addFacility" style="float: left; height: 22px; line-height: 22px; font-size: 10px"/>
				
	    <p:dataTable value="#{listFacilities.facilities}" var="facility" dynamic="true" paginator="true" rows="20" selectionMode="one"
	    			 emptyMessage="No Facilities" loadingMessage="Loading. . ." selection="#{listFacilities.selectedFacility}"
	    			 rowEditListener="#{listFacilities.rowEdit}" rendered="#{listFacilities.displayPage}" id="facilityList"
	    			 paginatorPosition="bottom"
	    >

			<f:facet name="header">
				Facility List
			</f:facet>  
	    
			<p:column headerText="Name" sortBy="#{facility.facilityName}">
				<p:cellEditor>  
					<f:facet name="output">
						<h:outputText value="#{facility.facilityName}" />
					</f:facet>
					<f:facet name="input">
						<h:inputText value="#{facility.facilityName}" style="width:100%" />
					</f:facet>	  
				</p:cellEditor> 
			</p:column>
			<p:column headerText="Address">
				<p:cellEditor>  
					<f:facet name="output">
						<h:outputText value="#{facility.address1}" />
					</f:facet>
					<f:facet name="input">
						<h:inputText value="#{facility.address1}" style="width:100%"/>  
					</f:facet>
				</p:cellEditor> 
			</p:column>
			<p:column headerText="City">
				<p:cellEditor>  
					<f:facet name="output">
						<h:outputText value="#{facility.city}" />
					</f:facet>
					<f:facet name="input">
						<h:inputText value="#{facility.city}" style="width:100%"/>
					</f:facet>  
				</p:cellEditor> 
			</p:column>
			<p:column headerText="State">
				<p:cellEditor>  
					<f:facet name="output">
						<h:outputText value="#{facility.state}" />
					</f:facet>
					<f:facet name="input">
						<h:inputText value="#{facility.state}" style="width:100%"/>  
					</f:facet>
				</p:cellEditor> 
			</p:column>
			<p:column headerText="Zip">
				<p:cellEditor>  
					<f:facet name="output">
						<h:outputText value="#{facility.postalCode}" />
					</f:facet>
					<f:facet name="input">
						<h:inputText value="#{facility.postalCode}" style="width:100%"/>  
					</f:facet>
				</p:cellEditor> 
			</p:column>
			<p:column headerText="URL">
				<p:cellEditor>  
					<f:facet name="output">
						<h:outputText value="#{facility.url}" />
					</f:facet>
					<f:facet name="input">
						<h:inputText value="#{facility.url}" style="width:100%"/>  
					</f:facet>
				</p:cellEditor> 
			</p:column>

			<p:column headerText="Options">
				<p:rowEditor />
			</p:column>
			<p:column>
				<p:commandLink actionListener="#{addFacility.modifyFacility}">
					<h:outputText value="Modify, " />
					<f:param name="facilityId" value="#{facility.facilityId}"/></p:commandLink>
				<p:commandLink actionListener="#{listFacilities.deleteFacility}" update="facilityList">
					<h:outputText value="Delete" />
					<f:param name="facilityId" value="#{facility.facilityId}"/></p:commandLink>
			</p:column>
		</p:dataTable>
		
		</h:form>
	</ui:define>

</ui:composition>

</html>
thanks for any help.
- Chris
PrimeFaces 3.0M1
Eclipse Indigo (with Tomcat 7.0.14)
Java 1.6
JSF 2.0 (Mojarra 2.0.4)
hibernate 3.5.5

cbmyers
Posts: 53
Joined: 20 Oct 2010, 14:56

02 Nov 2010, 14:11

Hi,

problem solved!

it was occurring because i had selectMode="one" in the datatable definition. It appears that selectMode for datatable defaults to multiple if it is not single, so the code was looking for #{listFacilities.selectedFacility} to be an array and it wasnt.

You might want to change this behavior to be single unless multiple is specified or just accept single or multiple and throw an error if it is anything else.

Thanks
- Chris
PrimeFaces 3.0M1
Eclipse Indigo (with Tomcat 7.0.14)
Java 1.6
JSF 2.0 (Mojarra 2.0.4)
hibernate 3.5.5

healeyb
Posts: 365
Joined: 07 Apr 2010, 16:05

02 Nov 2010, 14:34

Hi, far and away the best way to implement a commandLink in a
dataTable row that acts on the row in question is to pass a parameter
to the action routine. In your case this would involve doing this:

<p:commandLink action="#{listFacilities.deleteFacility(facility)
(facility parameter is var= from dataTable)

public String deleteFacility(Facility f) { ... }

This works well for me, I found myself getting into difficulties when
I didn't do this.

Brendan.

cbmyers
Posts: 53
Joined: 20 Oct 2010, 14:56

02 Nov 2010, 14:40

Thanks for your reply.

That method of passing parameters is not supported by mojarra or another part of my development stack. When i try to do it it get a syntax error in EL.

Thanks again.
- Chris
PrimeFaces 3.0M1
Eclipse Indigo (with Tomcat 7.0.14)
Java 1.6
JSF 2.0 (Mojarra 2.0.4)
hibernate 3.5.5

healeyb
Posts: 365
Joined: 07 Apr 2010, 16:05

02 Nov 2010, 15:05

I'm afraid you are incorrect, it is definitely supported by Mojarra EL as of v2.


Regards,
Brendan.

cbmyers
Posts: 53
Joined: 20 Oct 2010, 14:56

02 Nov 2010, 15:07

yeah, it must be some other part of my stack. eclipse definitely shows a syntax error when i try and pass a parameter in that manner.

thanks
- Chris
PrimeFaces 3.0M1
Eclipse Indigo (with Tomcat 7.0.14)
Java 1.6
JSF 2.0 (Mojarra 2.0.4)
hibernate 3.5.5

healeyb
Posts: 365
Joined: 07 Apr 2010, 16:05

02 Nov 2010, 15:26

Ok, you could just ignore the IDE and do it anyway. The problem is that
you can, and in fact are extremely likely to, click on the link without having
selected the row. Suppose the page has rendered and you've got a 3
facilities showing in the datatable. You have a delete link on one of the rows
and immediately click on it, i.e. hover the mouse over the link inside the
table and click.

The problem is that you've not selected a row. Using the method I described
you don't need to select the row, it's a smoother way of doing it.

Regards,
Brendan.

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 57 guests