Hi

Checking this issue I have found a good test for it:

forEach4.xhtml

<ui:composition>
    <ui:decorate template="forEach4_1.xhtml">
       <ui:param name="i" value="value"/>
       <ui:define name="header">
         <h:outputText value="#{i}"/>
       </ui:define>
    </ui:decorate>
</ui:composition>

forEach4_1.xhtml

<ui:composition>
  <c:forEach items="#{list}" var="i" varStatus="s" begin="0" end="10">
      <ui:insert name="header"/> = #{i}
  </c:forEach>
</ui:composition>

The example shows without doubt why c:forEach var and varStatus should
be only available inside c:forEach but with "page scope".

The outer page (forEach4.xhtml) adds a definition that suppose the
value passed inside ui:param is the one to be printed. Whatever
happens inside the template (forEach4_1.xhtml) shouldn't be a concern.
But in the inner page, #{i} should resolve according to c:forEach. If
#{list} is [A,B,C], the code should render:

value = A
value = B
value = C

If there is a ui:decorate or a ui:include inside c:forEach body, it
should pass the value through ui:param. The same is true for composite
components.

I'll attach a patch to solve this issue soon.
If no objections, I'll commit the changes soon.

regards,

Leonardo Uribe

2012/6/14 Leonardo Uribe <[email protected]>:
> Hi
>
> Trying to solve this issue:
>
> https://issues.apache.org/jira/browse/MYFACES-3520
>
> To keep things simple this is the example:
>
> Some xhtml:
> <c:forEach var="item" begin="1" end="3">
>    <div>
>        <ui:include src="templateContextTestInclude.xhtml">
>            <ui:param name="item" value="#{item + 10}" />
>        </ui:include>
>    </div>
> </c:forEach>
>
> templateContextTestInclude.xhtml:
>        <ui:composition>
>            Item: <h:outputText value="#{item}" /><br/>
>        </ui:composition>
>
> In few words, the problem is that the included page should not be
> affected by c:forEach tag. In this case the outer variable is used and
> the passed through ui:param is ignored.
>
> The current implementation uses facelets VariableResolver to store
> "var" and "varStatus values, but the problem is that it can "pass" across
> everything, including other templates and composite components and
> breaks encapsulation principle.
>
> Looking more carefully the spec javadoc of "var", it say this:
>
> "... Name of the exported scoped variable for the current item of
> the iteration. This scoped variable has nested visibility. Its type
> depends on the object of the underlying collection ...."
>
> In jsp, "nested visibility" means "... it can only be accessed within the
> body of the <c:forEach> tag. ....". This is clear, but in facelets the 
> original
> intention was lost.
>
> So, here we have an intepretation problem just like in:
>
> [jsf-spec] ui:param and c:set implementations does not work as
> expected (shouldn't page context and template context exists?)
>
> http://markmail.org/message/rlp6napyd6flhpje
>
> Like <c:set> and <ui:param>, <c:forEach> needs to be fixed. At
> first view I suggested to use TemplateContext, but now I'm thinking
> on use myfaces PageContext attribute map and restrict the scope.
> For example, the same example but using ui:decorate should
> work in the same way as with ui:include:
>
> Some xhtml:
> <c:forEach var="item" begin="1" end="3">
>    <div>
>        <ui:decorate template="templateContextTestInclude.xhtml">
>            <ui:param name="item" value="#{item + 10}" />
>        </ui:decorate>
>    </div>
> </c:forEach>
>
> templateContextTestInclude.xhtml:
>        <ui:composition>
>            Item: <h:outputText value="#{item}" /><br/>
>        </ui:composition>
>
> The intention with this change is the same as with the chance of
> c:set and ui:param : enforce encapsulation principle. I know
> c:forEach is a "relic from the past", and there are better components
> to do the same as this tag, but anyway I think it is worth to do it.
>
> I'll attach a patch to solve this issue soon.
>
> If no objections, I'll commit the changes soon.
>
> regards,
>
> Leonardo Uribe

Reply via email to