ajaxSingle inside rich:column of ExtendedDataModel
alibsd Jun 8, 2009 8:04 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