You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by Andrew Robinson <an...@gmail.com> on 2008/01/30 23:14:01 UTC
Partial triggers and "::" naming -- take 2
Sorry that this email is long, but it is a sensitive issue, so please read
on.
https://issues.apache.org/jira/browse/TRINIDAD-757
was reported because the behavior of the code did not match the JavaDoc
description.
Thread: http://tinyurl.com/373smc
At that time, it was decided by others that changing the JavaDoc would be
easier that changing the code.
The question became -- should "foo" work like UIComponent.findComponent() or
should it look it the parent component.
I have had feedback from people using Trinidad, that the change is breaking
current code, so the argument for not breaking ppl. by changing the JavaDoc
has not panned out.
Take this example:
<f:subview id="A">
<tr:group id="B">
<tr:panelGroupLayout id="C">
<tr:panelBox id="D">
<tr:commandButton id="E" />
<tr:table id="F" partialTriggers="#{pt}">
<tr:column>
<tr:commandButton id="G"/>...
Currently, if I want to F to trigger on G, I have to use #{pt} = "F:G". If I
want F to trigger on E, I have to use #{pt} = "E":
<tr:table id="F" partialTriggers="E">
<tr:table id="F" partialTriggers="F:G">
Not only is this confusing (well all solutions are a bit confusing
admittedly), but really bad for performance.
If #{pt} = "F:G", this is the code that happens (NC means NamingContainer.
"--" refers to the result):
comp = "F".getParent(); -- comp == "D"
check if comp is NC -- false
(repeat comp.getParent(), test for NC)
finds "A"
now call "A".findComponent("F:G")
UIComponent searches in this order to find "F":
A, B, C, D, E, F
(note that this code is broken if the JSF 1.2_04-p02 RI
UIComponentBase.findComponent() but is correct in MyFaces 1.1.5:
https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=690)
Now it searches all the children of F to find G
This code has way too much overhead. I was already at "F", why do I have to
search for it?
What would be cleaner:
<tr:table id="F" partialTriggers="::E">
<tr:table id="F" partialTriggers="G">
In the current implementation "::E" and "E" are identical!
In the "cleaner" approach "::E" and "E" are only identical if the current
component is not an NC.
If you read the UIComponent docs:
http://tinyurl.com/2dfak5
You will see that for the code
comp.findComponent("foo")
if comp is an NC, then it will check if comp is foo, or find the child that
is foo.
partialTriggers differs from this. That means that if a developer
understands the JSF method, they will not expect the partialTriggers
implementation.
What I (and a few of my co-workers) would prefer as the definition of
partialTriggers:
- If the search expression begins with a single ':', the base will be
the root UIComponent of the component tree. The leading separator character
will be stripped off, and the remainder of the search expression will be
treated as a "relative" search expression as described below.
- Otherwise, if this UIComponent is a NamingContainer it will serve as
the basis.
- Otherwise, search up the parents of this component. If a
NamingContainer is encountered, it will be the base.
- Otherwise (if no NamingContainer is encountered) the root
UIComponent will be the base.
- If the search expression starts with multiple ':' characters:
- For each ':' beyond the first, find the parent component that
is a NamingContainer. Therefore ':::comp' will begin the
"relative" search
from the NamingContainerthat is a ancestor of the
NamingContainer that comp
is a child of.
The search expression (possibly modified in the previous step) is now a
"relative" search expression that will be used to locate the component (if
any) that has an id that matches, within the scope of the base component.
The match is performed as follows:
- If the search expression is a simple identifier, this value is
compared to the id property, and then recursively through the facets and
children of the base UIComponent (except that if a descendant
NamingContainer is found, its own facets and children are not searched).
- If the search expression includes more than one identifier separated
by ':', the first identifier is used to locate a NamingContainer by the
rules in the previous bullet point. Then, the findComponent() method of this
NamingContainer will be called, passing the remainder of the search
expression.
This would improve performance, actually give a purpose to "::foo" and be in
sync with the method of searching for a component based on the JSF
specification.
Since we know current code is already broken, I do not feel that
"maintaining backward compatibility" is a valid reason to say no.
Thanks,
Andrew
PS - Wow, hard to believe you read all that, thanks! (or did you just scroll
to the end :-) )