[jsr-314-open] composite:insertFacet target facet name
Ken Paulsen
Ken.Paulsen at Sun.COM
Fri Sep 25 12:56:49 EDT 2009
Andy Schwartz wrote:
> Ken Paulsen wrote:
>>
>> Perhaps it's best to explain visually:
>>
>> Page author defines:
>> * Page A
>> * compComp
>> * facet "myfacet" : component X <-- not a child of panelGrid
>>
>> Component author defines:
>> * panelGrid
>> * facet "caption" : *reference* facet "myfacet" <-- non-child facet
>>
>> So instead of re-parenting "component X" from "compComp" to
>> "panelGrid", panelGrid maintains it's relationship that the page
>> author defines. Today's behavior does the re-parenting as soon as
>> you add it to the facet Map. A proxy-component might be possible
>> that acts like a "symbolic link" to the page author's component so
>> that the page author's original component doesn't get moved.
>
> Got it. The symbolic link analogy is good.
>
>>>>
>>>> If we were to explore not re-parenting, we'd probably need to
>>>> create a ProxyComponent which could be added to the child and
>>>> delegate everything to the real component which would remain on the
>>>> parent. That might work nicely.
>>>
>>> This sounds fairly close to what composite:renderFacet is doing, right?
>> Yes, but afaik, only for the "rendering" of the component.
>
> Right.
>
>> For example, if you ask for the "children" of the component put in
>> as a place holder for rendering, I don't think you'll get the
>> children defined by the page author... you'll get an empty list of
>> children b/c there are no children of the placeholder itself.
>
> Yep.
>
>>>
>>> Yep. So just to make sure I understand where you stand... Are you
>>> saying that you agree that we could handle these two cases:
>>>
>>> <!-- Insert "foo" facet into the component tree as a facet -->
>>> <composite:implementation>
>>> <h:panelGrid>
>>> <f:facet name="caption">
>>> <composite:insertFacet name="foo"/>
>>> </f:facet>
>>> </h:panelGrid>
>>> </composite:implementation>
>>>
>>>
>>> <!-- Insert "foo" facet into the component tree as a (non-facet)
>>> child -->
>>> <composite:implementation>
>>> <h:panelGroup>
>>> <composite:insertFacet name="foo"/>
>>> </h:panelGroup>
>>> </composite:implementation>
>>>
>>>
>>> With a single tag? But that you prefer that the tag does not
>>> actually perform re-parenting, ie. that the parent for the inserted
>>> component is the composite component itself in both cases?
>> Yes, that is what I was trying to say.
>
> Cool. I feel better now that we've sorted through this a bit. :-)
>
> It seems to me that there are two parts of this problem:
>
> - What the appropriate set of tags are to expose to composite
> component authors.
> - What the appropriate implementation is for inserting facets
> components into composite implementation components.
Yes. Although I believe the 2nd (the behavior) effects what should be
exposed in the first (interface). If the behavior (namely timing
restore-view phase vs. rendering phase; and the re-parenting behavior)
is so drastically different between these two, the tags should reflect
that. If the behavior is the same, there should only be 1 tag.
> As we've seen, the choice of #2 has impact on the page author.
>
> Regarding #1... It seems like we agree that it would be desirable to
> have a single tag that can perform three operations:
>
> 1. Insert a facet into the composite implementation as a facet of an
> arbitrary component using the same facet name.
> 2. Insert a facet into the composite implementation as a facet of an
> arbitrary component using a different facet name.
> 3. Insert a facet into the composite implementation as a direct child
> of an arbitrary component.
>
> Our current solution supports #1 via <composite:insertFacet>. We
> support #3 at least to some degree via <composite:renderFacet>, though
> there are subtle differences in behavior between this an
> <composite:renderFacet>.
I agree, we currently support #1 with insertFacet. However, I disagree
that we support #3 at all. This is the omitted use-case which we don't
support. I believe <composite:renderFacet> supports #4: "Rendering a
facet at the specified location". This is very different as #3 effects
tree walks, component creation, state saving, clientId's, and more. #4
simply tells the "renderer" of the composite component "when" to render
the user-supplied facet -- which is *exactly* how virtually every
Java-based component I have seen handles a facet supplied by a page author.
> I believe that #2 is also somewhat covered, though fails in certain
> cases (such as passing a facet into a nested composite component).
> These subtle differences are causing confusion about what should and
> shouldn't work, and I think are a general cause for concern with our
> current approach.
I don't feel #2 is sufficiently covered at all.
>
> Ideally, we should support #1, #2 and #3 with a single tag, and we
> would use the same insertion strategy for all three operations. So,
> we want an tag contract that is similar to ui:insert (single tag
> covers all cases), but actual insertion behavior is still open to debate.
I think the insertion behavior needs to be nailed down first. Then #1,
#2, #3 can be addressed, or #1, #2, and #4 (and maybe #3?) can be
addressed. Otherwise we don't know what the use cases are that we're
trying to solve.
>
> This is getting somewhat repetitive I know (sorry), but I'll ask one
> more time... Can anyone shed some light on why the multi-tag approach
> is preferable to the single tag approach - ie. is there a reason why
> we preferred not to follow the ui:insert model of having a single tag
> address all three of the above operations? It is possible that there
> is a good reason, and if so, I would feel more comfortable with our
> current solution if I knew what that reason was. :-)
As I mentioned above, 1 is a rendering tag which does not effect the
component tree. The other effects the component tree. If that behavior
stays the same, I am in favor of 2 tags. If we can change that behavior
so we essentially have "symbolic links" from the facet map and the child
list, then we have the same behavior and I'm in favor of 1 tag.
> Regarding the appropriate implementation for inserting facets into the
> composite implementation (whether as facets or as direct children)...
> This is a tough call... I understand Ken's concerns about breaking the
> abstraction for composite component users, though with the
> introduction of composite:insertFacet it seems that we were willing to
> accept this behavior (or, perhaps, were unaware of the side effects).
The more I think about the "side-effects" the more I am unhappy with
what we have... I firmly believe we made a mistake in allowing
re-parenting to happen. This diverges composite components from
Java-based components, and there should be no distinction between the
two (from the page author's perspective).
While I agree with your "advantages" below, I think the right answer
just hasn't been proposed. If you look at the table component, it has
the same "id" problem -- and solutions exist. I think repeated id's
need to be treated in a similar way for composite components when they
are inserted more than 1 time (now we're getting into the "fun" impl
details that I said Ryan or someone else would enjoy ;) ). This would
negate the "advantages" of a re-parenting solution, while retaining the
opaqueness of the component.
> One advantage that re-parenting has over referencing (symbolic link
> approach) is that re-parenting works with repeated component trees.
> That is...
>
> This works:
>
> <composite:implementation>
> <ui:repeat>
> <h:panelGrid>
> <composite:insertFacet name="caption"/>
> </h:panelGrid>
> </ui:repeat>
> </composite:implementation>
>
>
> But this fails in subtle ways:
>
> <composite:implementation>
> <ui:repeat>
> <h:panelGrid>
> <composite:renderFacet name="caption"/>
> </h:panelGrid>
> </ui:repeat>
> </composite:implementation>
>
>
> In particular, since the facet component does not end up as a child of
> the repeated component in the second case, the client ids will not be
> modified properly to reflect the current row. If the facet happened
> to be an input component, we would be out of luck.
>
> If I could make a single API change at this point, the one change that
> I would make would be to spec that <composite:insertFacet> determines
> the target facet name in the same way this is determined everywhere
> else - ie. by the presence of a wrapping <f:facet> tag. This would
> allow us to address all three of the above cases with a single tag
> with consistent behavior, which in my mind would be a huge
> improvement. (Presumably we could deprecate <composite:renderFacet>
> if we made this change.)
>
> However, this is a big change. It would mean that any existing cases
> that look like this:
>
> <composite:implementation>
> <h:panelGrid>
> <composite:insertFacet name="caption"/>
> </h:panelGrid>
> </composite:implementation>
>
> Would need to be changed to this:
>
> <composite:implementation>
> <h:panelGrid>
> <f:facet name="caption">
> <composite:insertFacet name="caption"/>
> </f:facet>
> </h:panelGrid>
> </composite:implementation>
>
> I am doubtful that we have the ability to make such a large change,
> but think it is at least worth considering.
I agree, considering the issues raised, I think we need to consider
deprecating some of this and replacing it with a better solution for 2.1.
> If we cannot do this now, things that we should think about:
>
> - Is there anything that we can do now that would limit the impact of
> the inconsistencies between our two composite facet tags?
> - Is there anything that we can do now to better support cases like #2
> above (insert facet using different name)? (This was the reason for
> my original email.)
I am in favor of adding an attribute name for the target facet name in
the short term (pre-2.1).
> - Where do we want to end up in 2.1?
My preference: 1 behavior and 1 tag (if we don't change the behavior, I
don't support 1 tag.)
Thanks Andy!!
Ken
> - Is there anything that we can do now that will help us get to where
> we want to be in 2.1?
>
>> I understand that may be much easier to *say* than implement,
>> though, as it poses several challenges -- many of which I probably
>> haven't thought through yet (such as how id's are resolved if it is
>> inserted 2x or more).
>
> Yep, I sense the implementation team cringing with every character
> that I type. ;-)
>
>
>>
>>>
>>> FWIW, even if we do not have the ability to make changes along these
>>> lines now, I am still interested in understanding/working through
>>> these problems so that we have a firm grasp of any
>>> limitations/complications present in our current APIs.
>> I agree, I like to think through these things as well for the sake of
>> understanding it better.
>
> Thanks Ken. It's been helpful working through these problems.
>
> Andy
>
More information about the jsr-314-open-mirror
mailing list