通过 Ajax 错误地刷新列表的 JSF
JSF refreshing list via Ajax incorrectly
我正在尝试将一些功能从 JQuery 迁移到 JSF,但我得到了奇怪的结果。
基本上它是一个页面,您可以在其中导航 links(想象成 Web 上的 Windows 资源管理器)。文件夹有 link 而叶子没有。为了构造它,它使用了 private List<Element> list;
,它会相应地刷新。因此,当用户单击 "folder" 时,将使用该文件夹的内容创建一个新的 list
。
问题是我得到了奇怪的结果。有时我导航 link 并且它被正确刷新,但在某些情况下它的行为就像页面被重新加载(但它没有)并且 list
被重置为其初始值(?)。例如,我导航到 "name2" 并得到正确的东西。但是后来我转到 "name2b",我得到的不是叶子,而是 "name1"、"name2" 和 "name3",它们仅在 init()
方法中设置。我不知道这是怎么发生的,但探索源代码似乎 c:foreach
结构与 id 混淆并且页面中呈现了旧 ID(请注意,我已经尝试 ui:repeat
同样错误的结果)。
我该如何解决这个问题?
这是简化代码:
<f:metadata>
<f:viewAction action="#{controller.init}" />
</f:metadata>
...
<h:panelGroup id="visor" layout="block">
<ul>
<c:forEach items="#{controller.list}" var="element">
<li>
<ui:fragment rendered="#{element.folder}">
<h:form>
<h:commandButton action="#{controller.navigate(element.name)}" type="submit" value="#{element.name}" >
<f:ajax render="visor" execute="@this" />
</h:commandButton>
</h:form>
</ui:fragment>
<ui:fragment rendered="#{not element.folder}">
<span>#{element.name}</span>
</ui:fragment>
</li>
</c:forEach>
</ul>
</h:panelGroup>
和控制器
@Named(value = "controller")
@ViewScoped
public class MyController implements Serializable {
private List<Element> list;
public void init() { //Called when loading the page
list = new ArrayList<>();
Element e1 = new Element("name1", true); //name and isFolder?
Element e2 = new Element("name2", true);
Element e3 = new Element("name3", true);
list.add(e1);
list.add(e2);
list.add(e3);
}
public void navigate(String name) {
list = new ArrayList<>();
if (name.equals("name1")) {
Element e1 = new Element("name1a", true);
Element e2 = new Element("name1b", true);
Element e3 = new Element("name1c", true);
list.add(e1); list.add(e2); list.add(e3);
} else if (name.equals("name2")) {
Element e1 = new Element("name2a", true);
Element e2 = new Element("name2b", true);
Element e3 = new Element("name2c", true);
list.add(e1); list.add(e2); list.add(e3);
} else {
Element e1 = new Element("leaf1", false);
Element e2 = new Element("leaf2", false);
list.add(e1); list.add(e2);
}
}
//....
编辑
我的问题好像描述的是in here。
我必须调查一下 是否可以为这个主题带来一些启发。
显然它是一个带有基本 JSF 的 that my structure cannot be dynamically updated in JSF. The solution I have to make is to use a h:datatable
instead of a <ul>
list (this is one thing I really dislike of JSF, but I am not sure how to render a list - 而不是我可以动态更新的 table。
Ajax render
属性必须指定 form
id。
<h:form id="visor">
<h:dataTable value="#{controller.list}" var="element">
<h:column>
....
<h:commandButton action=.... >
<f:ajax render="visor" execute="@this" />
</h:commandButton>
....
</h:column>
</h:dataTable>
</h:form>
编辑:UL
也有效,只要我渲染表单并且表单包含所有内容
我正在尝试将一些功能从 JQuery 迁移到 JSF,但我得到了奇怪的结果。
基本上它是一个页面,您可以在其中导航 links(想象成 Web 上的 Windows 资源管理器)。文件夹有 link 而叶子没有。为了构造它,它使用了 private List<Element> list;
,它会相应地刷新。因此,当用户单击 "folder" 时,将使用该文件夹的内容创建一个新的 list
。
问题是我得到了奇怪的结果。有时我导航 link 并且它被正确刷新,但在某些情况下它的行为就像页面被重新加载(但它没有)并且 list
被重置为其初始值(?)。例如,我导航到 "name2" 并得到正确的东西。但是后来我转到 "name2b",我得到的不是叶子,而是 "name1"、"name2" 和 "name3",它们仅在 init()
方法中设置。我不知道这是怎么发生的,但探索源代码似乎 c:foreach
结构与 id 混淆并且页面中呈现了旧 ID(请注意,我已经尝试 ui:repeat
同样错误的结果)。
我该如何解决这个问题?
这是简化代码:
<f:metadata>
<f:viewAction action="#{controller.init}" />
</f:metadata>
...
<h:panelGroup id="visor" layout="block">
<ul>
<c:forEach items="#{controller.list}" var="element">
<li>
<ui:fragment rendered="#{element.folder}">
<h:form>
<h:commandButton action="#{controller.navigate(element.name)}" type="submit" value="#{element.name}" >
<f:ajax render="visor" execute="@this" />
</h:commandButton>
</h:form>
</ui:fragment>
<ui:fragment rendered="#{not element.folder}">
<span>#{element.name}</span>
</ui:fragment>
</li>
</c:forEach>
</ul>
</h:panelGroup>
和控制器
@Named(value = "controller")
@ViewScoped
public class MyController implements Serializable {
private List<Element> list;
public void init() { //Called when loading the page
list = new ArrayList<>();
Element e1 = new Element("name1", true); //name and isFolder?
Element e2 = new Element("name2", true);
Element e3 = new Element("name3", true);
list.add(e1);
list.add(e2);
list.add(e3);
}
public void navigate(String name) {
list = new ArrayList<>();
if (name.equals("name1")) {
Element e1 = new Element("name1a", true);
Element e2 = new Element("name1b", true);
Element e3 = new Element("name1c", true);
list.add(e1); list.add(e2); list.add(e3);
} else if (name.equals("name2")) {
Element e1 = new Element("name2a", true);
Element e2 = new Element("name2b", true);
Element e3 = new Element("name2c", true);
list.add(e1); list.add(e2); list.add(e3);
} else {
Element e1 = new Element("leaf1", false);
Element e2 = new Element("leaf2", false);
list.add(e1); list.add(e2);
}
}
//....
编辑
我的问题好像描述的是in here。
我必须调查一下
显然它是一个带有基本 JSF 的 h:datatable
instead of a <ul>
list (this is one thing I really dislike of JSF, but I am not sure how to render a list - 而不是我可以动态更新的 table。
Ajax render
属性必须指定 form
id。
<h:form id="visor">
<h:dataTable value="#{controller.list}" var="element">
<h:column>
....
<h:commandButton action=.... >
<f:ajax render="visor" execute="@this" />
</h:commandButton>
....
</h:column>
</h:dataTable>
</h:form>
编辑:UL
也有效,只要我渲染表单并且表单包含所有内容