jsf c:forEach in h:dataTable in Partial View

时间:2015-04-15 21:01:25

标签: jsf cdi

当我们突然发现一个重复的任务时,我们决定用一个部分视图来处理学校项目。它基本上是一个由保存在@Named@SessionScoped(两个CDI)bean中的列表编译而成的表。

partialView.xhtml的代码:

<ui:composition>
    <h:dataTable
            /* Style */>
        <c:forEach items="#{playListVM.playList.songs}" var="song">
            <f:facet name="caption">
                #{playListVM.playList.name}
            </f:facet>
            <h:column>
                <f:facet name="header">Index</f:facet>  
                #{playListVM.playList.songs.indexOf(song)+1}
            </h:column>
...

我想多次调用这个“方法”:

home.xhtml的代码:

<c:forEach items="#{c.playLists}" var="playList">
    <ui:include src="#{c.playListPV(playList)}" />          
</c:forEach>

playListPV(playlist)playListVM.playList的值设置为playList,并将path返回到.xhtml文件。

首先我们只使用h:dataTable尝试它,只要我们每次渲染使用一次partialView(否则它使用相同的引用并且每个PV都相同)。所以我用Google搜索了更多内容,并且我每次调用方法时都会覆盖对象。然后我读了这篇文章关于c:forEach以及事物呈现的顺序。我们在这里。

到现在为止,我认为整个方法都是错误的......

3 个答案:

答案 0 :(得分:4)

我认为你最初是这样试过的:

<h:dataTable value="#{c.playLists}" var="playList">
    <ui:include src="#{c.playListPV(playList)}" />          
</h:dataTable>

这确实不会按照您的预期运作。 <ui:include>在视图构建期间作为标记处理程序运行,而<h:dataTable>在视图呈现时间内作为UI组件运行,在视图构建时间之后。因此,在<ui:include>运行的那一刻,#{playList}未在范围内设置。实际上,您最终会得到一个src等于c.getPlayListPV(null)的包含。

您需要在视图构建时创建多个<ui:include>。您应该使用在视图构建期间运行的迭代标记处理程序。 JSTL <c:forEach>确实是这样的。为了使代码更清晰,transform the include file into a tag file

也就是说,“部分视图”一词在JSF中的含义与您的想法完全不同。这与<ui:include>无关。术语“部分视图”涉及在部分请求期间处理的视图部分(即,它正是<f:ajax execute><f:ajax render>所涵盖的那些组件。

另见:

答案 1 :(得分:1)

  

到现在为止,我认为整个方法都是错误的......

我认为你是对的,你对ui-include标签的期望是错误的。该 只需将包含的文件复制粘贴到目标文件中即可替换ui-include标记;换句话说,您在示例中所做的只是在循环中附加相同的Facelets组件。

包含文件没有特殊的变量范围。输出只渲染一次,渲染时将使用playListVM.playList的最终值。

我认为你可以通过以下方式实现目标:

<c:forEach items="#{playListVM.playlists}" var="playlist">
  <c:forEach items="#{playlist.songs}" var="song">

我并不完全是这个意思;您需要根据自己的应用进行调整。

答案 2 :(得分:1)

如果我理解你正在尝试做的事情,这是一个基本的工作示例。

PlayListMB:

@Named
@ViewScoped
public class PlayListMB implements Serializable {

    private static final long serialVersionUID = 1L;

    private List<List<String>> listOfPlayLists;

    public PlayListMB() {
        listOfPlayLists = new ArrayList<List<String>>();
        for (int i = 0; i < 5; i++) {
            List<String> playlist = new ArrayList<String>();
            for (int j = 0; j < 5; j++) {
                playlist.add("song" + String.valueOf(i+1) + String.valueOf(j+1));
            }
            listOfPlayLists.add(playlist);
        }
    }

    public List<List<String>> getListOfPlayLists() {
        return listOfPlayLists;
    }
}

singlelist.xhtml:

<ui:composition>

    <h:dataTable value="#{playList}" var="songName">
        <h:column>
            <f:facet name="header">Index</f:facet>  
            #{playList.indexOf(songName) + 1}
        </h:column>
        <h:column>
            <f:facet name="header">Song Name</f:facet>  
            #{songName}
        </h:column>
    </h:dataTable>

</ui:composition>

index.xhtml:

<h:head>
</h:head>
<h:body>

    <c:forEach items="#{playListMB.listOfPlayLists}" var="playList">
        <ui:include src="singlelist.xhtml"/>
    </c:forEach>

</h:body>