reRender in <a4j:commandLink> NOT WORKING, generated 'affect
rhinox Mar 27, 2007 2:51 AMHi,
I have the following:
Ajax4jsf 1.1.0
Apache Tomahawk 1.1.3
Facelets 1.1.11
JSF RI 1.2_04-b10-p01
Sun App Server 9.1 (build b33e-beta)
test.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:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:t="http://myfaces.apache.org/tomahawk" xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"> <f:view> <t:document> <t:documentHead> <meta http-equiv="content-type" content="text/xhtml; charset=utf-8; pageEncoding=utf-8"/> <meta http-equiv="pragma" content="no-cache"/> <meta http-equiv="cache-control" content="no-cache"/> <meta http-equiv="expires" content="0"/> <title>Test</title> </t:documentHead> <t:documentBody> <a4j:form> <a4j:region> <div style="height: 300px; overflow: auto; border: 1px solid red"> <a4j:log level="ALL" popup="false" width="400" height="200"/> </div> <a4j:outputPanel id="data"> <t:dataList id="groups" var="group" value="#{bean.groups}"> <t:div id="group"> <h:outputText value="Group Name"/> <t:div> <h:outputText value="#{group.name}"/> <a4j:commandLink action="#{bean.delete}" value="delete group" immediate="true" reRender="data" limitToList="true"> <!--<a4j:ajaxListener type="org.ajax4jsf.ajax.ForceRender"/>--> <f:param name="id" value="#{group.id}"/> </a4j:commandLink> </t:div> <t:dataList id="item" var="item" value="#{group.items}"> <t:div> <h:outputText value="#{item.name}"/> <a4j:commandLink action="#{bean.delete}" value="delete" immediate="true" reRender="data" limitToList="true"> <f:param name="id" value="#{item.id}"/> </a4j:commandLink> </t:div> </t:dataList> </t:div> </t:dataList> </a4j:outputPanel> </a4j:region> </a4j:form> </t:documentBody> </t:document> </f:view> </html>
Bean.java
package com.test.jsf; import javax.faces.context.*; import java.util.*; public final class Bean { private List<Group> groups; // private DataModel dataModel; public Bean() { // dataModel = new ListDataModel(); groups = new ArrayList<Group>(); Group group = new Group(1, "Group 1"); group.addItem(new Item(group, 1, "Item 1")); group.addItem(new Item(group, 2, "Item 2")); group.addItem(new Item(group, 3, "Item 3")); groups.add(group); group = new Group(2, "Group 2"); group.addItem(new Item(group, 4, "Item 4")); group.addItem(new Item(group, 5, "Item 5")); group.addItem(new Item(group, 6, "Item 6")); groups.add(group); group = new Group(3, "Group 3"); group.addItem(new Item(group, 7, "Item 7")); group.addItem(new Item(group, 8, "Item 8")); group.addItem(new Item(group, 9, "Item 9")); groups.add(group); } // public DataModel getGroups() { // dataModel = new ListDataModel(groups); // return dataModel; // } public List<Group> getGroups() { return groups; } public String delete() { FacesContext facesContext = FacesContext.getCurrentInstance(); ExternalContext externalContext = facesContext.getExternalContext(); Item item = (Item) externalContext.getRequestMap().get("item"); if (item != null) item.getGroup().removeItem(item); return null; } public String deleteGroup() { FacesContext facesContext = FacesContext.getCurrentInstance(); ExternalContext externalContext = facesContext.getExternalContext(); Group group = (Group) externalContext.getRequestMap().get("group"); if (group != null) groups.remove(group); return null; } }
Group.java
package com.test.jsf; import javax.faces.model.*; import java.util.*; public final class Group { private int id; private String name; private List<Item> items; // private DataModel dataModel; public Group(int id, String name) { this.id = id; this.name = name; items = new ArrayList<Item>(); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } // public DataModel getItems() { // dataModel = new ListDataModel(items); // return dataModel; // } public List<Item> getItems() { return items; } public void addItem(Item item) { items.add(item); } public void removeItem(Item item) { items.remove(item); } }
Item.java
package com.test.jsf; public final class Item { private int id; private String name; private Group group; public Item() { } public Item(Group group, int id, String name) { this.group = group; this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Group getGroup() { return group; } }
faces-config.xml
<?xml version='1.0' encoding='UTF-8'?> <faces-config xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd" version="1.2"> <managed-bean> <managed-bean-name>bean</managed-bean-name> <managed-bean-class>com.test.jsf.Bean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> </faces-config>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <description>Test</description> <display-name>Test</display-name> <!-- Facelets ViewHandler --> <context-param> <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name> <param-value>com.sun.facelets.FaceletViewHandler</param-value> </context-param> <!-- Custom Libraries --> <context-param> <param-name>facelets.LIBRARIES</param-name> <param-value>/WEB-INF/facelets/tags/tomahawk.taglib.xml</param-value> </context-param> <!-- Use Documents Saved as *.xhtml --> <context-param> <param-name>javax.faces.DEFAULT_SUFFIX</param-name> <param-value>.xhtml</param-value> </context-param> <!-- Special Debug Output for Development --> <context-param> <param-name>facelets.DEVELOPMENT</param-name> <param-value>true</param-value> </context-param> <!-- Optional JSF-RI Parameters to Help Debug --> <context-param> <param-name>com.sun.faces.verifyObjects</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>com.sun.faces.validateXml</param-name> <param-value>true</param-value> </context-param> <!-- State Saving Method --> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param> <!-- Apache MyFaces Tunning --> <context-param> <param-name>org.apache.myfaces.ADD_RESOURCE_CLASS</param-name> <param-value>org.apache.myfaces.component.html.util.StreamingAddResource</param-value> </context-param> <context-param> <param-name>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</param-name> <param-value>false</param-value> </context-param> <context-param> <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name> <param-value>false</param-value> </context-param> <context-param> <description>Only applicable if state saving method is "server" (= default). Defines the amount (default = 20) of the latest views are stored in session. </description> <param-name>org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION</param-name> <param-value>20</param-value> </context-param> <!-- Ajax4jsf Filter --> <filter> <display-name>Ajax4jsf Filter</display-name> <filter-name>ajax4jsf</filter-name> <filter-class>org.ajax4jsf.Filter</filter-class> </filter> <filter-mapping> <filter-name>ajax4jsf</filter-name> <servlet-name>Faces Servlet</servlet-name> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> </filter-mapping> <!--Apache MyFaces Extension Filter (Tomahawk requirement) --> <filter> <filter-name>MyFacesExtensionsFilter</filter-name> <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class> <init-param> <param-name>maxFileSize</param-name> <param-value>20m</param-value> </init-param> </filter> <!--extension mapping for adding <script/>, <link/>, and other resource tags to JSF-pages --> <filter-mapping> <filter-name>MyFacesExtensionsFilter</filter-name> <!--servlet-name must match the name of your javax.faces.webapp.FacesServlet entry --> <servlet-name>Faces Servlet</servlet-name> </filter-mapping> <!--extension mapping for serving page-independent resources (javascript, stylesheets, images, etc.) --> <filter-mapping> <filter-name>MyFacesExtensionsFilter</filter-name> <url-pattern>/faces/myFacesExtensionResource/*</url-pattern> </filter-mapping> <!--extension mapping for adding <script/>, <link/>, and other resource tags to JSF-pages --> <filter-mapping> <filter-name>MyFacesExtensionsFilter</filter-name> <url-pattern>*.faces</url-pattern> </filter-mapping> <!-- Faces Servlet --> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- Faces Servlet Mapping --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.faces</url-pattern> </servlet-mapping> </web-app>
The problem is when I click on any of the a4j:commandLinks the AJAX response searches for a 'data' node id instead of a 'xxx:data' so no update occurs (the 'affected' attribute is ALWAYS generated without the parent UIComponent prefix unless the commandLink is NOT inside a dataList). I think this is an ajax4jsf bug cause if the commandLink is out of the dataList object the 'affected' property points correctly to 'xxxx:data'.
I've try all possible 'solutions': a4j:ajaxListener with force render, dataTable instead of dataList, a4j:repeat instead of dataList, a4j:outputPanel, reRender='groups' instead of 'data', everything!. The only way I get the data component updated is setting its ajaxRendered property to true but this is out of the question, I can't do that cause I have several a4j:outputPanel on the same page and I want to update independently, not all at once each time a commandLink is executed.
Please HELP!
Thanks