reRender in <a4j:commandLink> in t:dataTable or t:dataList N
nils_eckert May 22, 2007 6:43 PMHello together,
I have a Problem similar to http://jboss.com/index.html?module=bb&op=viewtopic&t=105067&postdays=0&postorder=asc&start=0
My Environment is:
* Ajax4JSF 1.1 an 1.1.1-SNAPSHOT tried
* Tomcat 5.5
* MyFaces 1.1.5
* Facelets 1.1.11
* Tomahawk
* Trinidad 1.0.0 Incubating
On my page there is a h:inputText, where the user can enter a String. When the form is submitted, a customers, that match this string are listed with a h:dataTable or h:dataList.
Each row / element contains a a4j:commandLink with a a4j:actionparam to set the customer to the accountForm.
If I click the link, the request is done. But nothing happens.
If I render the list with a c:forEach and create the a4j:commandLink "by hand" it works.
So I think there is a Problem, detecting the correct element.
I tried the Ajax4jsf 1.1.1 SNAPSHOT. And build a ajax4jsf from the current svn trunk yesterday. All that didn't help.
Thanks for your help.
Regards,
Nils Eckert
Here is the Code:
accountForm.xhtml
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="http://java.sun.com/jstl/core" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:t="http://myfaces.apache.org/tomahawk" xmlns:a4j="https://ajax4jsf.dev.java.net/ajax"> <f:view> <ui:composition template="layout.xhtml"> <ui:define name="title">#{text['accountForm.title']}</ui:define> <ui:define name="content"> <a4j:log hotkey="L" /> <t:saveState id="account" value="#{accountForm.account}" /> <f:loadBundle var="text" basename="#{accountForm.bundleName}" /> <t:messages showDetail="true" showSummary="false" /> <h:form id="accountForm"> <div style="float: right;"><h:panelGroup styleClass="buttonBar bottom"> <h:commandButton value="#{text['button.save']}" action="#{accountForm.save}" id="save" styleClass="button" /> <c:if test="${not empty accountForm.account.id}"> <h:commandButton value="#{text['button.delete']}" action="#{accountForm.delete}" id="delete" styleClass="button" /> </c:if> <h:commandButton value="#{text['button.cancel']}" action="cancel" immediate="true" id="cancel" styleClass="button" /> </h:panelGroup></div> <h1>#{text['accountForm.heading']}</h1> <table> <tr> <td><t:panelGroup> <h:outputLabel styleClass="desc" for="id" value="#{text['account.id']}" /> <h:inputText styleClass="text small" id="id" value="#{accountForm.account.key.id}" readonly="true" /> </t:panelGroup></td> <td><t:panelGroup> <h:outputLabel styleClass="desc" for="date" value="#{text['account.date']}" /> <t:inputCalendar id="date" styleClass="text small" value="#{accountForm.account.date}" renderAsPopup="true" popupTodayString="#{example_messages['popup_today_string']}" popupDateFormat="dd.MM.yyyy" popupWeekString="#{example_messages['popup_week_string']}" helpText="dd.MM.yyyy" forceId="true" popupButtonImageUrl="images/fam_silk_icons/calendar.png" renderPopupButtonAsImage="true"> <f:convertDateTime pattern="dd.MM.yyyy" timeZone="CET"/> </t:inputCalendar> <t:message for="date" styleClass="fieldError" /> </t:panelGroup></td> <td><t:panelGroup> <h:outputLabel styleClass="desc" for="customer" value="#{text['customer.fullname']}" /> <h:inputText styleClass="text large" id="customer" value="#{accountForm.account.customer.fullName}" readonly="true" /> <t:message for="customer" styleClass="fieldError" /> </t:panelGroup></td> </tr> </table> </h:form> </ui:define> <ui:define name="right"> <div class="box"><a4j:form ajaxSubmit="true" reRender="customerSearchResult"> <h:outputLabel for="input" styleClass="desc" value="Kundensuche:" /> <h:inputText id="userName" styleClass="text medium" value="#{customerList.searchString}" /> <a4j:commandButton value="GO" image="images/fam_silk_icons/zoom.png" /> </a4j:form><a4j:outputPanel id="customerSearchResult"> <c:choose> <c:when test="#{not empty customerList.searchResult}"> <h:form class="smallHeightOverflow"> <h:dataTable value="#{customerList.searchResult}" var="customer" styleClass="table" rowClasses="odd, even"> <h:column> <a4j:commandLink id="chooseCustomer" value="#{customer.fullName}" reRender="customer, customerno" action="#{accountForm.update}" styleClass="output"> <a4j:actionparam name="customerNo" assignTo="#{accountForm.customerNo}" value="#{customer.key.id}" /> </a4j:commandLink> </h:column> </h:dataTable> </h:form> </c:when> <c:when test="#{customerList.searchString}"> <p>Keine Kunden gefunden.</p> </c:when> </c:choose> </a4j:outputPanel></div> </ui:define> </ui:composition> </f:view> </html>
AccountForm.java
package de.neckert.webapp.action; import java.io.Serializable; import java.math.BigDecimal; import java.util.Map; import java.util.TreeMap; import javax.faces.context.FacesContext; import de.neckert.model.Account; import de.neckert.model.AccountItem; import de.neckert.model.Customer; import de.neckert.service.AbstractAccountManager; import de.neckert.webapp.action.base.BasePage; public class AccountForm extends BasePage implements Serializable { private static final long serialVersionUID = 4604220211994183235L; private AbstractAccountManager<Account> accountManager; private Account account = new Account(); private AccountItem currentItem; private Long id; private Map<String, String> unities; private TreeMap<String, Float> taxPositions; public void setAccountManager(AbstractAccountManager<Account> accountManager) { this.accountManager = accountManager; } public Account getAccount() { return account; } public void setAccount(Account account) { this.account = account; } public AccountItem getCurrentItem() { if (currentItem == null) { currentItem = new AccountItem(); currentItem.setQuantity(1.0f); currentItem.setUnity("Std."); currentItem.setTax(0.19f); currentItem.setPrice(new BigDecimal(60)); currentItem.setName("Administration"); } return currentItem; } public void setCurrentItem(AccountItem currentItem) { this.currentItem = currentItem; } public void setId(Long id) { this.id = id; } public String edit() { if (id != null) { account = accountManager.get(getKey(id)); } else { account = new Account(); } return EDIT; } public String addItem() { getAccount().addItem(currentItem); currentItem = null; return EDIT; } public String update() { return null; } public void setCustomerNo(Long id) { if (id != null) { Customer customer = getCustomerManager().get(getKey(id)); if (customer != null) { account.setCustomer(customer); } } } public String save() { boolean isNew = (account.getId() == null); account.getKey().setUser(getUser()); accountManager.save(account); String key = (isNew) ? "account.added" : "account.updated"; addMessage(key); if (isNew) { return LIST; } else { return EDIT; } } }
CustomerList.java
package de.neckert.webapp.action; import java.util.ArrayList; import java.util.List; import de.neckert.model.Customer; import de.neckert.service.CustomerManager; import de.neckert.webapp.action.base.BasePage; public class CustomerList extends BasePage { private CustomerManager customerManager; private String searchString; private List<Customer> searchResult; public CustomerList() { setSortColumn("id"); } public void setCustomerManager(CustomerManager customerManager) { this.customerManager = customerManager; } public String getSearchString() { return searchString; } public void setSearchString(String searchString) { this.searchString = searchString; } public List<Customer> getCustomers() { return customerManager.getAll(sortColumn, ascending, getUser()); } public List<Customer> getSearchResult() { if (searchResult == null) { List<Customer> result; if (searchString != null && searchString.length() != 0) { result = customerManager.find(searchString, getUser()); } else { result = new ArrayList<Customer>(); } sortColumn = "fullName"; searchResult = sort(result); } return searchResult; } }
faces-config.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd"> <faces-config> <application> <variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver> <locale-config> <default-locale>de</default-locale> <supported-locale>en</supported-locale> </locale-config> <message-bundle>ApplicationResources</message-bundle> <view-handler>com.sun.facelets.FaceletViewHandler</view-handler> </application> SNIP... </faces-config>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>NEFO3</display-name> <distributable /> <!-- precompiled jsp mappings --> <!-- Define the default CSS Theme --> <context-param> <param-name>csstheme</param-name> <param-value>neis</param-value> </context-param> <!-- Define the basename for a resource bundle for I18N --> <context-param> <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name> <param-value>ApplicationResources</param-value> </context-param> <!-- Fallback locale if no bundles found for browser's preferred locale --> <!-- Force a single locale using param-name 'javax.servlet.jsp.jstl.fmt.locale' --> <context-param> <param-name>javax.servlet.jsp.jstl.fmt.fallbackLocale</param-name> <param-value>en</param-value> </context-param> <!-- Context Configuration locations for Spring XML files --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:/applicationContext-resources.xml classpath*:/applicationContext-dao.xml classpath*:/applicationContext-service.xml classpath*:/applicationContext.xml /WEB-INF/applicationContext*.xml /WEB-INF/security.xml </param-value> </context-param> <!-- FaceletViewHandler configuration --> <context-param> <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name> <param-value>com.sun.facelets.FaceletViewHandler</param-value> </context-param> <context-param> <param-name>javax.faces.DEFAULT_SUFFIX</param-name> <param-value>.xhtml</param-value> </context-param> <context-param> <param-name>org.apache.myfaces.trinidad.ALTERNATE_VIEW_HANDLER</param-name> <param-value>com.sun.facelets.FaceletViewHandler</param-value> </context-param> <context-param> <param-name>org.apache.myfaces.trinidad.CACHE_VIEW_ROOT</param-name> <param-value>false</param-value> </context-param> <!-- Use client-side state saving. In Trinidad, it is an optimized, token-based mechanism that is almost always a better choice than the standard JSF server-side state saving. --> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>client</param-value> <!--param-value>server</param-value--> </context-param> <context-param> <param-name>facelets.DEVELOPMENT</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>facelets.SKIP_COMMENTS</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>facelets.LIBRARIES</param-name> <param-value>/WEB-INF/taglibs/corejsf-validator.taglib.xml; /WEB-INF/taglibs/tomahawk.taglib.xml</param-value> </context-param> <filter> <filter-name>ajax4jsf</filter-name> <filter-class>org.ajax4jsf.Filter</filter-class> </filter> <filter> <filter-name>trinidad</filter-name> <filter-class>org.apache.myfaces.trinidad.webapp.TrinidadFilter</filter-class> </filter> <!-- <filter> <filter-name>cacheFilter</filter-name> <filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class> </filter> --> <!-- <filter> <filter-name>clickstreamFilter</filter-name> <filter-class>com.opensymphony.clickstream.ClickstreamFilter</filter-class> </filter> --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter> <filter-name>extensionsFilter</filter-name> <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class> <init-param> <param-name>maxFileSize</param-name> <param-value>2m</param-value> </init-param> </filter> <filter> <filter-name>gzipFilter</filter-name> <filter-class>net.sf.ehcache.constructs.web.filter.GzipFilter</filter-class> </filter> <!-- Remove this filter if you're using iBATIS, use OpenEntityManagerInViewFilter if using JPA --> <filter> <filter-name>lazyLoadingFilter</filter-name> <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> <!--<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>--> </filter> <filter> <filter-name>localeFilter</filter-name> <filter-class>org.appfuse.webapp.filter.LocaleFilter</filter-class> </filter> <filter> <filter-name>messageFilter</filter-name> <filter-class>org.appfuse.webapp.filter.MessageFilter</filter-class> </filter> <filter> <filter-name>rewriteFilter</filter-name> <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class> <init-param> <param-name>logLevel</param-name> <param-value>log4j</param-value> </init-param> </filter> <filter> <filter-name>securityFilter</filter-name> <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class> <init-param> <param-name>targetClass</param-name> <param-value>org.acegisecurity.util.FilterChainProxy</param-value> </init-param> </filter> <filter> <filter-name>sitemesh</filter-name> <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class> </filter> <filter-mapping> <filter-name>ajax4jsf</filter-name> <servlet-name>faces</servlet-name> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> <filter-mapping> <filter-name>trinidad</filter-name> <servlet-name>faces</servlet-name> </filter-mapping> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>securityFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>extensionsFilter</filter-name> <servlet-name>faces</servlet-name> </filter-mapping> <filter-mapping> <filter-name>extensionsFilter</filter-name> <url-pattern>/faces/myFacesExtensionResource/*</url-pattern> </filter-mapping> <!-- Commented out for 2 reasons: 1) it's a pain when developing JSPs, and 2) it causes the Signup webtest to fail --> <!--filter-mapping> <filter-name>cacheFilter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping--> <filter-mapping> <filter-name>lazyLoadingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- <filter-mapping> <filter-name>clickstreamFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> --> <filter-mapping> <filter-name>localeFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>gzipFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>rewriteFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> <!-- <filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping>--> <filter-mapping> <filter-name>messageFilter</filter-name> <url-pattern>*.html</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> <listener> <listener-class>com.opensymphony.clickstream.ClickstreamListener</listener-class> </listener> <listener> <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> <listener> <listener-class>org.appfuse.webapp.listener.StartupListener</listener-class> </listener> <listener> <listener-class>org.appfuse.webapp.listener.UserCounterListener</listener-class> </listener> <listener> <listener-class>net.sf.navigator.menu.MenuContextListener</listener-class> </listener> <servlet> <servlet-name>faces</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <!-- resource loader servlet --> <servlet> <servlet-name>resources</servlet-name> <servlet-class>org.apache.myfaces.trinidad.webapp.ResourceServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>faces</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>resources</servlet-name> <url-pattern>/adf/*</url-pattern> </servlet-mapping> <session-config> <session-timeout>10</session-timeout> </session-config> <security-constraint> <web-resource-collection> <web-resource-name>Protect XHTML Templates</web-resource-name> <url-pattern>*.xhtml</url-pattern> </web-resource-collection> <auth-constraint /> </security-constraint> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <error-page> <error-code>500</error-code> <location>/error.jsp</location> </error-page> <error-page> <error-code>400</error-code> <location>/index.jsp</location> </error-page> <error-page> <error-code>403</error-code> <location>/403.jsp</location> </error-page> <error-page> <error-code>404</error-code> <location>/404.jsp</location> </error-page> </web-app>