如何在zk中动态树中选择父节点时选择所有子节点?

时间:2016-07-13 12:46:30

标签: java zk zul

我目前在zk中使用动态树。代码如下:

<tree id="treeview"  multiple="true" width="330px" model="@load(vm.treeModel)"
                          style="border: 1px solid #9D9D9D;"  vflex="1" rows="14" >
                        <treecols sizable="true">
                            <treecol />
                        </treecols>
                        <template name="model">
                            <treeitem>
                                <treerow>
                                    <treecell><checkbox label="@load(each.data.name)" checked="true"/></treecell>
                                </treerow>
                            </treeitem>
                        </template>
                  </tree>

我希望如果我取消选中父复选框,则必须取消选中所有子项。 反之亦然,即如果我检查父复选框,则必须检查所有子项。

zk中是否有可用于树标记的属性来执行此操作? 如果没有,还有其他方法吗?

2 个答案:

答案 0 :(得分:0)

我遇到了同样的问题,并提出了一个仅限客户端的解决方案,它可以快速准确地引发正确的选择事件。

要启用它,请在树项呈示器中添加此小部件侦听器:

treeitem.setWidgetListener(Events.ON_CLICK, "selectSubTreesOnItemClick(this, event);");

在你的情况下(模板),这样做:

<tree xmlns:w="client">
  ...
    <treeitem w:onClick="selectSubTreesOnItemClick(this, event)">

然后,导入以下js文件(在您的zul中,在某处添加<script src="/js/treeselection.js" />):

function selectSubTreesOnItemClick(item, event) {
    // if clicked outside of check box, reset selection
    if (!jq(event.target).is('.z-treerow')) {
        item.getTree().clearSelection();

        // re-select clicked node
        item.setSelected(true);
    }

    privateSelectDescendants(item);

    privateSelectParentIfAllDescendantsSelected(item);

    // update selection
    item.getTree().fireOnSelect(item);

    // prevent interference of the tree's default click behavior (like selection of the clicked node ;) ).
    event.stop();
}

/**
 * @param parent if selected, selects all children (and grand-children and so on), otherwise
 *                  removes them from selection.
 */
function privateSelectDescendants(parent) {
    var items = parent.getTree().itemIterator();

    // find all descendants of parent
    while (items.hasNext() && items.next() !== parent) {}
    var stopAt = privateGetFirstNonDescendant(parent);

    // check descendants
    while (items.hasNext()) {
        var descendant = items.next();
        if (descendant === stopAt) {
            break;
        } else {
            descendant.setSelected(parent.isSelected());
        }
    }
}

/**
 * @param item parent will be selected if item and all its siblings are selected, otherwise
 *                 unselected. Repeated for grandparents, great-grandparents, and so on.
 */
function privateSelectParentIfAllDescendantsSelected(item) {
    if (item.getParentItem() != null) {
        var parent = item.getParentItem();

        // find all descendants of parent
        var items = parent.getTree().itemIterator();
        while (items.hasNext()) {
            if (items.next() === parent){
                break;
            }
        }
        var stopAt = privateGetFirstNonDescendant(parent);

        // check descendants
        var allDescendantsSelected = true;
        while (items.hasNext()) {
            var child = items.next();
            if (child === stopAt) {
                break;
            } else if (!child.isSelected()) {
                allDescendantsSelected = false;
                break;
            }
        }
        parent.setSelected(allDescendantsSelected);

        // continue with grandparents
        privateSelectParentIfAllDescendantsSelected(parent);
    }
}

/**
 * @param item
 * @returns the next item that is on the same or a higher level as item. 
 *             Undefined if item is the last node or only followed by children.
 */
function privateGetFirstNonDescendant(item) {
    var result = item.nextSibling;

    while (!result && item.getParentItem() != null) {
        item = item.getParentItem();
        result = item.nextSibling;
    }

    return result;
}

(Un)选择树节点也将(un)选择其后代。此外,如果选择了所有节点的兄弟节点,则将选择父节点,否则将取消选择(这将一直到根节点)。

答案 1 :(得分:0)

您可以将Zscript用于您的目的,通过onclick事件,您可以链接到函数并将Treeitem作为参数传递。该函数评估是否有子代,在子代之间循环并根据是否选择父代进行设置。如果有很多嵌套嵌套,则可以使用递归函数。

<zscript><![CDATA[
  public void selectItemsChildren(Treeitem item){
    item.setOpen(true);
    if(!item.isEmpty())
      for(Treeitem p : item.getTreechildren().getItems()){
        p.setSelected(item.isSelected());
      }
    }
  ]]>
</zscript> 
<tree id="treeAccess" width="100%" model="@bind(vm.treeModel)">
  <treecols>
    <treecol hflex="1" label="Description"/>
  </treecols>
  <template name="model">
    <treeitem onClick="selectItemsChildren(self)">
      <treerow>
        <treecell label="@load(each...any)"/>
      </treerow>
    </treeitem>
  </template>
</tree>