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