1 Reply Latest reply on Jun 8, 2009 8:17 AM by ilya_shaikovsky

    ajaxSingle inside rich:column of ExtendedDataModel

    alibsd

      Hi,

      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