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>