Issue Details (XML | Word | Printable)

Key: JAVASERVERFACES-2958
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Manfred Riem
Reporter: jasonzhang2002gmailcom
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
javaserverfaces

component with UI data can not be resolved properly by UIRepeat

Created: 22/Jul/13 09:36 PM   Updated: 08/Jan/14 10:19 PM   Resolved: 21/Oct/13 01:22 PM
Component/s: ajax
Affects Version/s: 2.2.1
Fix Version/s: 2.2.5

Time Tracking:
Not Specified

File Attachments: 1. Text File changebundle.txt (1 kB) 11/Oct/13 07:56 PM - Manfred Riem

Environment:

glassfish 4, mojarra 2.2.1


Tags: ajax ui_repeat ui_data
Participants: jasonzhang2002gmailcom and Manfred Riem


 Description  « Hide

CODE

package resources;

import java.io.Serializable;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;

import javax.faces.view.ViewScoped;
import javax.inject.Named;

@ViewScoped
@Named
public class Test implements Serializable
{

	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	List<Integer> ints=new ArrayList<Integer>();
	ValueHolderList vl=new ValueHolderList();
	
	public Test()
	{
		ints.add(1);
		/*
		ints.add(2);
		ints.add(3);
		ints.add(4);
		ints.add(5);
		*/
	}
	
	
	public ValueHolderList getList()
	{
		return vl;
	}
	
	public void removeInt(int index)
	{
		ints.remove(index);
	}
	
	public class ValueHolder
	{

		int index;

		
		public ValueHolder(int index)
		{
			super();
			this.index = index;
		}

		public int getValue()
		{
			if (index>=ints.size())
			{
				return 0;
			}
			return ints.get(index);
		}

		public void setValue(int value)
		{
			ints.set(index, value);
		}
	}
	public class ValueHolderList extends AbstractList<ValueHolder>
	{
		public ValueHolderList()
		{
			super();	
		}

		public ValueHolder get(int index)
		{
			return new ValueHolder(index);
		}



		@Override
		public int size()
		{
			return ints.size();
		}
	}
}

Facelet

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://xmlns.jcp.org/jsf/html"
	xmlns:f="http://xmlns.jcp.org/jsf/core"
	xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
</h:head>
<h:body>
	<h:form id="f">
		<h:panelGroup id="top">
			<table>
				<ui:repeat var="valueHolder" value="#{test.list}" varStatus="status" id="r">
					<tr>
						<td><h:inputText value="#{valueHolder.value}" id="i"></h:inputText></td>
						<td><h:inputText value="5">
							<f:ajax render=":f:r:0:i"></f:ajax>
						
						</h:inputText></td>
						<td><h:commandButton value="remove" id="b"
								actionListener="#{test.removeInt(status.index)}">
								<f:ajax execute=":f:top" render=":f:top"></f:ajax>

							</h:commandButton></td>
							
					</tr>
				</ui:repeat>
			</table>
		</h:panelGroup>
	</h:form>
</h:body>
</html>

Exception

javax.faces.FacesException: <f:ajax> contains an unknown id ':f:r:0:i' - cannot locate it in the context of the component j_idt7
	at com.sun.faces.renderkit.html_basic.AjaxBehaviorRenderer.getResolvedId(AjaxBehaviorRenderer.java:305)
	at com.sun.faces.renderkit.html_basic.AjaxBehaviorRenderer.appendIds(AjaxBehaviorRenderer.java:292)
	at com.sun.faces.renderkit.html_basic.AjaxBehaviorRenderer.buildAjaxCommand(AjaxBehaviorRenderer.java:225)
	at com.sun.faces.renderkit.html_basic.AjaxBehaviorRenderer.getScript(AjaxBehaviorRenderer.java:89)
	at javax.faces.component.behavior.ClientBehaviorBase.getScript(ClientBehaviorBase.java:103)
	at com.sun.faces.renderkit.RenderKitUtils.getSingleBehaviorHandler(RenderKitUtils.java:1679)

In this trivial example, :f:r:0:i is a perfect id for input. The issue is that when UIRepeat tries to find child components, it looks its children for a component with id 0 while 0 is the row number.

I just use this example to reproduce the problem. In reality, I have a very complicated ID like this :ie:ConditionQuery:Conditions:r:0:QueryCondition:Operator:controls. The ID is generated from EL like this *:#{cc.parent.clientId}:controls*. As a composite component developer, I have no control whether my component is used under UIRepeat or not.

-jason



jasonzhang2002gmailcom added a comment - 22/Jul/13 09:39 PM

The title is not appropriate. It should be component under UIRepeat can not be resolved properly by UIRepeat. But I can not change it after I posted it.


jasonzhang2002gmailcom added a comment - 23/Jul/13 12:31 AM

If I replace ':f:r:0:i' with ':f:r:i', everything works as expected.


jasonzhang2002gmailcom added a comment - 23/Jul/13 03:32 AM

I read the document carefully. String in render attributes should be client ID. Given this, :f:r:i is not a valid clientID while :f:r:0:i is a valid client ID. :f:r:i works under the same table. But there is no way to support cross-row ajax interaction, or support interaction between a component out of UIRepeat and a component in a particular row in UIRepeat.


Manfred Riem added a comment - 21/Oct/13 01:22 PM

Applied to 2.2 branch,

svn commit -m "Fixes https://java.net/jira/browse/JAVASERVERFACES-2958, allow for f:ajax to default back to a client id, without actually resolving it."
Sending jsf-ri/src/main/java/com/sun/faces/renderkit/html_basic/AjaxBehaviorRenderer.java
Transmitting file data .
Committed revision 12606.