Primefaces 为什么';p:ajax更新&x27;更新p:树失败?
我想产生这样的结果,即每当树节点展开时,之前展开的任何同级节点都会折叠 下面是我的页面和我的bean。展开节点时调用onNodeExpanded方法;System.out语句生成预期结果。但是,执行setExpanded(false)的节点在页面上保持展开状态 我添加了一个commandButton,以便强制更新树。按下该键将在页面中正确显示之前由ajax事件侦听器折叠的节点 页面:Primefaces 为什么';p:ajax更新&x27;更新p:树失败?,primefaces,Primefaces,我想产生这样的结果,即每当树节点展开时,之前展开的任何同级节点都会折叠 下面是我的页面和我的bean。展开节点时调用onNodeExpanded方法;System.out语句生成预期结果。但是,执行setExpanded(false)的节点在页面上保持展开状态 我添加了一个commandButton,以便强制更新树。按下该键将在页面中正确显示之前由ajax事件侦听器折叠的节点 页面: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transiti
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>PrimeFaces Tree: Ajax Update Problem</title>
</h:head>
<h:body>
<h3>PrimeFaces Tree: Ajax Update Problem</h3>
<h:form>
<p:tree id="tree" value="#{problemController.root}" var="node" dynamic="true" orientation="horizontal">
<p:treeNode>
<h:outputText value="#{node}" />
</p:treeNode>
<p:ajax event="expand" listener="#{problemController.onNodeExpanded}" update="tree" />
</p:tree>
<h:commandButton value="Update" immediate="true">
<f:ajax render="tree" />
</h:commandButton>
</h:form>
</h:body>
</html>
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import org.primefaces.event.NodeExpandEvent;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
@Named
@ViewScoped
public class ProblemController implements Serializable {
private static final long serialVersionUID = 1L;
private TreeNode root;
@PostConstruct
public void init() {
root = new DefaultTreeNode("Root", null);
TreeNode node0 = new DefaultTreeNode("Node 0", root);
TreeNode node1 = new DefaultTreeNode("Node 1", root);
TreeNode node00 = new DefaultTreeNode("Node 0.0", node0);
TreeNode node01 = new DefaultTreeNode("Node 0.1", node0);
TreeNode node10 = new DefaultTreeNode("Node 1.0", node1);
node1.getChildren().add(new DefaultTreeNode("Node 1.1"));
node00.getChildren().add(new DefaultTreeNode("Node 0.0.0"));
node00.getChildren().add(new DefaultTreeNode("Node 0.0.1"));
node01.getChildren().add(new DefaultTreeNode("Node 0.1.0"));
node10.getChildren().add(new DefaultTreeNode("Node 1.0.0"));
root.getChildren().add(new DefaultTreeNode("Node 2"));
}
public TreeNode getRoot() {
return root;
}
public void onNodeExpanded(NodeExpandEvent event) {
TreeNode expandedNode = event.getTreeNode();
System.out.printf("Expanded %s\n", expandedNode);
TreeNode parent = expandedNode.getParent();
if (parent != null) {
for (TreeNode sibling : parent.getChildren()) {
if (sibling.isExpanded() && sibling != expandedNode) {
sibling.setExpanded(false);
System.out.printf("Collapsed %s\n", sibling);
}
}
}
}
}
Java 1.8 PrimeFaces 6.1 Mojarra 2.3 Weld 3.0
更新1
我已经用@Kukeltje提供的代码更新了页面。不幸的是,扩展节点的兄弟节点没有被折叠。我在closeOthers函数中添加了一条语句,该语句记录到控制台:显示我展开的任何节点的数据(“root”或“0”或“0_1”,等等)(如预期的那样)
素数面树
素数面树
//
从组件本身内部的ajax调用中更新完整组件并不常见。由于您使用了dynamic=“true”
,因此与不使用dynamic=“true”
相比,您看到的负面影响更少。如果更新p:tree
周围的容器,也会发生同样的情况。实际上,树上有两个相互冲突的更新,特别是当试图隐藏节点时
实际上,您似乎试图通过使用服务器端的树操作(这本身并没有错),一次只打开一个节点。这确实与中尝试的内容有关,但这个问题的表述过于狭隘,因为它不是关于选择/取消选择或隐藏/取消隐藏,而是更一般的问题,即无法从组件中的ajax调用中更新完整的树组件
仍应在服务器端更新内容,以便仍支持完全刷新。但是,您可以尝试使用oncomplete
javascript回调关闭客户端的所有其他节点,而不是执行update=“tree”
添加以下javascript将为您做到这一点:
<h:outputScript>
//<![CDATA[
function closeOthers(current, widget) {
var dataRowkey = $.urlParam(decodeURIComponent(current.data),current.source+"_expandNode");
//For a vertical tree:
//var selector = "li[data-rowkey='"+dataRowkey+"']";
//$(widget.jq).find(selector).siblings().find("span[aria-expanded='true']").siblings(".ui-tree-toggler").trigger("click");
//For a horizontal tree
var selector = "td[data-rowkey='"+dataRowkey+"']";
// The first attempt was to look for aria-expanded=true but we
// found that sometimes it would be present on a collapsed node (bug?).
// $(widget.jq).find(selector).parent().parent().parent().siblings().find("td[aria-expanded='true']").find(".ui-tree-toggler").trigger("click");
// Searching instead for the minus icon did the trick
$(widget.jq).find(selector).parent().parent().parent().siblings().find(".ui-icon-minus").trigger("click");
}
$.urlParam = function (query, name) {
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(query);
return (results !== null) ? results[1] || 0 : false;
}
//]]>
</h:outputScript>
很可能您没有将节点的状态保存到某个地方,而只是再次完全呈现(例如bean的范围)?请学习在发布问题时如何创建问题列表。这使我们在尝试帮助时变得更加容易,因为我们不必开始猜测或提问,或者……有任何进展吗?@Kukeltje我用一个MCV示例更新了这个问题。谢谢你的帮助。我找到了原因/解释。将在今晚或明天写一个答案。太棒了!老兄,我正在考虑为树组件制作一个“补丁”,这样你就可以配置一个“始终打开的单个节点”,使它成为组件的一部分!
<h:outputScript>
//<![CDATA[
function closeOthers(current, widget) {
var dataRowkey = $.urlParam(decodeURIComponent(current.data),current.source+"_expandNode");
//For a vertical tree:
//var selector = "li[data-rowkey='"+dataRowkey+"']";
//$(widget.jq).find(selector).siblings().find("span[aria-expanded='true']").siblings(".ui-tree-toggler").trigger("click");
//For a horizontal tree
var selector = "td[data-rowkey='"+dataRowkey+"']";
// The first attempt was to look for aria-expanded=true but we
// found that sometimes it would be present on a collapsed node (bug?).
// $(widget.jq).find(selector).parent().parent().parent().siblings().find("td[aria-expanded='true']").find(".ui-tree-toggler").trigger("click");
// Searching instead for the minus icon did the trick
$(widget.jq).find(selector).parent().parent().parent().siblings().find(".ui-icon-minus").trigger("click");
}
$.urlParam = function (query, name) {
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(query);
return (results !== null) ? results[1] || 0 : false;
}
//]]>
</h:outputScript>
<p:tree id="tree" widgetVar="treeW" value="#{problemController.root}" var="node" orientation="horizontal">
<p:treeNode>
<h:outputText value="#{node}" />
</p:treeNode>
<p:ajax event="expand" listener="#{problemController.onNodeExpanded}" oncomplete="closeOthers(this, PF('treeW'))"/>
</p:tree>