使用< c:set>的EL变量;内部Facelets< ui:repeat>标签 [英] Using EL variable of <c:set> inside Facelets <ui:repeat> tags

查看:113
本文介绍了使用< c:set>的EL变量;内部Facelets< ui:repeat>标签的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Home.每个Home都有一个Room的列表.每个Room具有零个或多个Person.

I have a Home. Each Home has a list of Rooms. Each Room has zero or more Persons.

我想计算每个家庭的总人数.但是我无法添加新变量来记录任何支持bean或实体中的人员计数.因此,我只想通过<c:set>在视图中对其进行计数.

I would like to count total persons of each home. But I can't add a new variable to record person count in any backing beans or entity. So I'd like to count it in the view only via <c:set>.

我的第一次尝试如下:

<c:set var="personCount" value="${0}" />
<ui:repeat var="home" value="#{mybackingBean.homes}">
    <ui:repeat var="room" value="#{home.rooms}">
        ${personCount += room.persons.size()}
    </ui:repeat>
    <h:panelGrid columns="2">
        <h:outputLabel value="#{home.id}" />
        <h:outputLabel value="#{personCount}" />
    </h:panelGrid>
</ui:repeat>

我该如何实现?

推荐答案

有几个错误.

首先

${personCount += room.persons.size()}

在EL中,+=字符串串联运算符.因此,这基本上将为您提供String.valueOf(personCount) + String.valueOf(size)的结果.如果计数初始化为0并且有3个人,则将打印03.

In EL, the += is the string concatenation operator. So, this will give you basically the result of String.valueOf(personCount) + String.valueOf(size). If the count is initialized to 0 and there are 3 persons, then this will print 03.

您基本上想将personCount + size的结果重新分配回变量personCount.您需要使用<c:set>重新设置变量,如下所示.

You basically want to re-assign the result of personCount + size back to variable personCount. You need to re-set the variable using <c:set> as below.

<c:set var="personCount" value="${personCount + room.persons.size()}" />


第二,


Second,

<c:set var="personCount" value="${0}" />
<[for each home]>
    <[for each room]>
        <c:set var="personCount" value="${personCount + room.persons.size()}" />

在两个迭代之外,都用0初始化了personCount.因此,对于每个房屋,您也将以这种方式计算以前所有房屋的人数.您想在第一次迭代中声明它.

The personCount is initialized with 0 outside both iterations. So, for each home you'll this way count the persons of all previous homes as well. You want to declare it inside the first iteration.

<[for each home]>
    <c:set var="personCount" value="${0}" />
        <[for each room]>
            <c:set var="personCount" value="${personCount + room.persons.size()}" />

这与EL不相关.这只是一个逻辑错误,也会在普通香草" Java中引起同样的问题.

This is not EL related. This is just a logic error which would cause the same problem in "plain vanilla" Java as well.

第三,

JSTL标记在视图构建期间(从XHTML模板转换为JSF组件树期间)运行.诸如<ui:repeat>之类的JSF组件在视图渲染期间运行(在从JSF组件树到HTML输出的转换过程中).因此,<c:set>不会在<ui:repeat>迭代期间运行.因此,它看不到迭代变量var.基本上,您还需要在视图构建期间进行迭代.您可以为此使用JSTL <c:forEach>.

JSTL tags like <c:set> run during view build time (during conversion from XHTML template to JSF component tree). JSF components like <ui:repeat> run during view render time (during conversion from JSF component tree to HTML output). So, the <c:set> doesn't run during <ui:repeat> iteration. Thus, it cannot see the iteration variable var. You basically need to iterate during view build time as well. You can use JSTL <c:forEach> for this.

因此,总而言之,您打算使用的解决方案如下所示:

So, all in all, your intented solution look like this:

<c:forEach items="#{bean.homes}" var="home">
    <c:set var="personCount" value="${0}" />
    <c:forEach items="#{home.rooms}" var="room">
        <c:set var="personCount" value="${personCount + room.persons.size()}" />
    </c:forEach>

    <h:panelGrid columns="2">
        <h:outputLabel value="#{home.id}" />
        <h:outputLabel value="#{personCount}" />
    </h:panelGrid>
</c:forEach>

有关深入的解释,另请参见 JSF2 Facelets中的JSTL ...很有意义?

For an in depth explanation, see also JSTL in JSF2 Facelets... makes sense?

但是,由于+=运算符显然不会导致EL异常,这意味着您已经在使用EL 3.0.反过来,这意味着您可以使用新的 EL 3.0 lambda和流功能.

However, as the += operator apparently doesn't cause an EL exception in your case, this means that you're already using EL 3.0. This in turn means that you can use the new EL 3.0 lambda and stream features.

<ui:repeat value="#{bean.homes}" var="home">
    <h:panelGrid columns="2">
        <h:outputLabel value="#{home.id}" />
        <h:outputLabel value="#{home.rooms.stream().map(room -> room.persons.size()).sum()}" />
    </h:panelGrid>
</ui:repeat>

不再需要计数循环.不,这不需要Java 8,它可以在Java 7上很好地工作.

No need for a counting loop anymore. No, this does not require Java 8, it works on Java 7 as good.

这篇关于使用&lt; c:set&gt;的EL变量;内部Facelets&lt; ui:repeat&gt;标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆