分部视图中 h:dataTable 中的 jsf c:forEach

jsf c:forEach in h:dataTable in a PartialView

在做一个学校项目时,我们突然发现一个重复性很高的任务,所以我们决定从中创建一个 partialView。它基本上是 table 从保存在 @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>
...

我想像这样多次调用这个 "method":

home.xhtml代码:

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

playListPV(playlist)playListVM.playList 的值设置为 playList,将 returns path 的值设置为 .xhtml 文件。

首先,我们只在 h:dataTable 上进行了尝试,只要我们每次渲染使用一次 partialView 就可以正常工作(否则它使用相同的引用并且每个 PV 都是相同的)。所以我在谷歌上搜索了更多,发现我每次调用该方法时都会覆盖该对象。然后我阅读了这篇关于 c:forEach 和渲染顺序的文章。我们到了。

现在我认为整个方法是错误的...

By now I think the whole approach is wrong...

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

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

我认为你可以通过这样的方式实现你的目标:

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

我不是这个意思;您需要对其进行调整以适合您的应用程序。

我了解到您最初是这样尝试的:

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

这确实不会像您预期的那样工作。 <ui:include> 在视图构建期间作为标记处理程序运行,而 <h:dataTable> 在视图渲染期间作为 UI 组件运行,即 after[=40] =] 视图构建时间。因此,在 <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> 涵盖的那些组件)。

另请参阅:

  • JSTL in JSF2 Facelets... makes sense?
  • How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)

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

播放列表MB :

@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>