Pergunta

I am using dynatree to select multi-nodes in a hierarchy of directories.

So, I have investigated the behavior of all built-in options for selectMode, but, unfortunately, none of them resolves my problem:

  • 1: single-selection (not my case)
  • 2: multi-selection
    • it does not select the parent node when all children nodes are selected (ok)
    • it does not select all children nodes when the parent node is selected (not ok)
  • 3: hierarchical multi-selection
    • it selects the parent node when all children nodes are selected (not ok)
    • it selects all children nodes when the parent node is selected (ok)

The behavior for my case would be correct if:

  • it does not select the parent node when all children nodes are selected
    • selecting all children directories is different from selecting the parent of them
  • it selects all children nodes when the parent node is selected
    • otherwise, the user might not understand that the children are also selected

Question #1: How to implement this behavior?

Furthermore, the dtnode.tree.getSelectedNodes() is returning redundant nodes:

/Foo
/Foo/Bar

If /Foo is selected, it is already implied that /Foo/Bar is selected, for me.

Question #2: How to optimize the selected nodes redundancy?

Foi útil?

Solução

The best solution that I see involves using selectMode: 2 and toggling the visibility of the children's checkboxes when selecting a node:

//enable or disable redundant children nodes recursively
function toggleChildrenNodes(disableChildren, dtnode) {
    if (!dtnode)
        return;

    if (!dtnode.childList)
        return;

    for (var chIdx = 0; chIdx < dtnode.childList.length; chIdx++) {
        dtnode.childList[chIdx].data.hideCheckbox = disableChildren;
        dtnode.childList[chIdx].render(true);
        //when re-enabling a child node that was previously selected, it should disable their children
        toggleChildrenNodes(disableChildren || dtnode.childList[chIdx].isSelected(), dtnode.childList[chIdx]);
    }
}

$('#myTree').dynatree({
    selectMode: 2,
    checkbox: true,
    onSelect: function(isSelected, dtnode) {
        if(!dtnode)
            return;

        toggleChildrenNodes(isSelect, dtnode);

        //gets the optimized selected nodes
        var dryNodes = $.map(dtnode.tree.getSelectedNodes(), function(currentSelectedNode, idx) {
            if (!currentSelectedNode.data.hideCheckbox) { //skip redundant nodes
                return currentSelectedNode.data.key;
            }
            return null;
        });
        console.log(dryNodes);
    }
});

Additionally, if the tree nodes expansion is lazy, it is necessary to handle the new children nodes to keep the consistency:

onLazyRead: function(dtnode) {
    if(!dtnode)
        return;

    //[...] business logic

    //[...] possible iteration to add N children

    dtnode.addChild({
        //[...] other properties

        //creates childnode with the checkbox hidden if the parent is selected or hidden due to a higher ancestor
        hideCheckbox: dtnode.isSelected() || dtnode.data.hideCheckbox
    });
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top