[ 
https://issues.apache.org/jira/browse/MYFACES-3904?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14045397#comment-14045397
 ] 

Leonardo Uribe commented on MYFACES-3904:
-----------------------------------------

Now I can remember the problem and why we decided to send always the clientId 
of the component as source attribute.

The problem is the 'source' attribute can be any id, but there is no way to do 
properly the mapping between the id and the component.
This is done usually with the clientId, so only if the clientId is added in 
this location, the mapping can be done and then the decoding will work 
properly. 

But in this case, the "source" of the function jsf.util.chain(...) is used to 
for something else. In this case, this field is used to define the context of 
the method.

The clientId is an unique identifier that binds the UIComponent instance and a 
DOM element in the html markup tree. Use some other id in "source" field 
doesn't make any sense in the server side. 

JSF 2.0 section 14.2.3 says this:

"...Values for the execute and render attributes are not required. When using 
the JavaScript API, the default values for execute is @this. The default value 
for render is @none. ..."

And then it says that:

jsf.ajax.request(this,event); 

is the same as:

jsf.ajax.request(this,event,{execute:’@this’,render:’@this’});

This works well because the ajax is always added in the top HTML element that 
has as id the clientId of the component that has the behavior attached. But in 
the case of h:selectManyCheckbox for example, we do not have that case, but the 
code doesn't have any idea about where this is rendered. 

How the f:ajax behavior can know where it is rendered? When 
ClientBehaviorContext.createClientBehaviorContext(...) is called, the sourceId 
is passed too.

This is what the javadoc of ClientBehaviorContext.getSourceId() says:

"... Returns an id for use as the ClientBehavior source. ClientBehavior 
implementations that submit back to the Faces lifecycle are required to 
identify which component triggered the ClientBehavior-initiated request via the 
javax.faces.source request parameter. In most cases, th source id can be 
trivially derived from the element to which the behavior's client-side script 
is attached - ie. the source id is typically the id of this element. However, 
in components which produce more complex content, the behavior script may not 
be able to determine the correct id to use for the javax.faces.source value. 
The getSourceId() method allows the component to pass this information into the 
ClientBehavior.getScript(javax.faces.component.behavior.ClientBehaviorContext) 
implementation. ..."

Then it says this:

"...return the id for the behavior's script to use as the "source", or null if 
the Behavior's script can identify the source from the DOM. ..."

So, there is a confusion between the value that pass javax.faces.source and the 
values that javax.faces.partial.execute has. 

Additionally, it looks like the "source" field of jsf.util.chain(...) is 
special and is not the same as the one used in jsf.ajax.request(...). Why? 
because in jsf.util.chain(...) "source" has the purpose of define the context, 
so when the methods are called, "this" can be properly set.

The easiest fix I can imagine is do not use targetClientId or the sourceId in 
jsf.util.chain(...) and use "this" instead, but do not change anything else. It 
is not pretty, but I think it is justified. I can't imagine another case when 
jsf.util.chain use other different value as "this".

There is still the chance to fix the renderers, so they can use "this" instead 
"document.getElementById(...)". That will reduce the amount of rendered 
javascript, but the effort is too high, because we need to update the current 
logic we have in the renderer code, and do that will introduce new bugs. Maybe 
it could be done for 2.2.x.

Let us know if the patch proposed fix the problem and if that so, I'll commit 
it. I know the patch doesn't fix the problem fully, but it is the best option 
so far, and it has passed a long time since 2.0 until someone detected it. So, 
this bug is not very relevant, it has an easy fix, it is difficult to solve, 
the probability of introduce new bugs is too high. 

> jsf.util.Chain() is rendered with wrong event source
> ----------------------------------------------------
>
>                 Key: MYFACES-3904
>                 URL: https://issues.apache.org/jira/browse/MYFACES-3904
>             Project: MyFaces Core
>          Issue Type: Bug
>    Affects Versions: 2.2.0
>            Reporter: Sven Linstaedt
>         Attachments: MYFACES-3904-1.patch
>
>
> When applying multiple behaviors to an component, they are rendered to be 
> executed in chain by using jsf.util.chain(). So far so good. 
> When applying a behavior to a component, that renders multiple html input 
> elements like h:selectManyCheckbox or h:selectOneRadio, the javascript is 
> generated for every html elements, from which everyone gets it's own id 
> rendered by appending a ongoing number to the clientId of the component. In 
> the myfaces renderer code these Ids are called itemId.
> The problem is, when you apply multiple behaviors to components, which render 
> multiple html input elements: in this case all behaviors are wrapped in a 
> chained call, which unfortunately receives not the itemId of the currently 
> rendered html element as the source parameter, but the clientId of the 
> component. According to the spec, the source parameter should contain "the 
> DOM element that triggered this Ajax request, or an id string of the element 
> to use as the triggering element." 
> Because the event handler is bound to the html input element and not to it's 
> parent html "wrapping" element used for layouting, the wrong event source is 
> rendered in my option, which leads to the following side effect: Behavior 
> scripts, that reference the current event producing html element via "this" 
> will receive a different calling context ("this), if chain together with 
> multiple behaviors than, if they would as single behavior, leading to all 
> behavior scripts referencing "this" to run in the wrong context and often 
> doing nothing meaningful at all.
> E.g.: chained invocation of 
> {code}
> <input id="form:shipmentDateCriteriaOption:0" type="radio" 
> name="form:shipmentDateCriteriaOption" value="NEXT_WEEK" 
> onchange="$(this).val('')">
> {code}
> and
> {code}
> <input id="form:shipmentDateCriteriaOption:0" type="radio" 
> name="form:shipmentDateCriteriaOption" value="NEXT_WEEK" 
> onchange="jsf.ajax.request('form:shipmentDateCriteriaOption',event,{'javax.faces.behavior.event':'valueChange'})">
> {code}
> is rendered as:
> {code}
> <input id="form:shipmentDateCriteriaOption:0" type="radio" 
> name="form:shipmentDateCriteriaOption" value="NEXT_WEEK" 
> onchange="jsf.util.chain(document.getElementById('form:shipmentDateCriteriaOption'),
>  event,'$(this).val(\'\')', 
> 'jsf.ajax.request(\'form:shipmentDateCriteriaOption\',event,{\'javax.faces.behavior.event\':\'valueChange\'})');">
> {code}



--
This message was sent by Atlassian JIRA
(v6.2#6252)

Reply via email to