ajaxSingle inside rich:column of ExtendedDataModel
alibsd Jun 8, 2009 8:07 AMHi,
The problem seems to be related to sending single Ajax requests from
inside rich:column, when value of rich:dataTable is generated by use
of ExtendedDataModels.
To explain the situation, I post my code:
cmd.xhtml
<!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:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich"> <body> <h:form> <rich:dataTable value="#{testBean.dataModel}" var="name"> <rich:column> <h:outputText value="#{name}" /> <a4j:commandLink actionListener="#{testBean.actionDummy}" ajaxSingle="false" value="CC" /> </rich:column> </rich:dataTable> </h:form> </body> </html>
and the backing bean (session scoped):
package com.sg; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.faces.context.FacesContext; import javax.faces.event.ActionEvent; import javax.faces.model.DataModel; import org.ajax4jsf.model.DataVisitor; import org.ajax4jsf.model.ExtendedDataModel; import org.ajax4jsf.model.Range; public class TestBean { private List<String> names; public TestBean() { names = new ArrayList<String>(); names.add("Jack"); names.add("George"); names.add("John"); names.add("Leon"); } public DataModel getDataModel() { return new ExtendedDataModel() { private int rowIndex; private String pk; private List<String> wrappedKeys; private Map<String, String> wrappedData = new HashMap<String, String>(); @Override public Object getRowKey() { return pk; } @Override public void setRowKey(Object key) { this.pk = (String) key; } @Override public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException { wrappedKeys = new ArrayList<String>(); for (String val : names) { wrappedKeys.add(val); wrappedData.put(val, val); visitor.process(context, val, argument); } } @Override public int getRowCount() { return names.size(); } @Override public Object getRowData() { if (pk == null) { return null; } else { return wrappedData.get(pk); } } @Override public int getRowIndex() { return rowIndex; } @Override public Object getWrappedData() { throw new UnsupportedOperationException(); } @Override public boolean isRowAvailable() { return (pk != null); } @Override public void setRowIndex(int rowIndex) { this.rowIndex = rowIndex; } @Override public void setWrappedData(Object data) { throw new UnsupportedOperationException(); } }; } public void actionDummy(ActionEvent e) { System.err.println("IN ACTION DUMMY"); } }
Everything works find if ajaxSingle is set to false, but by setting it to "true",
the actionListener method (actionDummy) is not called.
I traced the code of JSF and A4J and it seems that in cases that ajaxSingle=true,
in AjaxViewRoot.processPhase line 246 which calls invokeOnComponent,
no equal component is found, so actionEvent is not queued and hence
the actionListener is not called.
I hope my explanation could be helpful.
Regards