在 dijit.Tree 中搜索

Posted

技术标签:

【中文标题】在 dijit.Tree 中搜索【英文标题】:Search in dijit.Tree 【发布时间】:2012-07-23 10:55:42 【问题描述】:

在我的一个项目中,我使用了 dijit.Tree 控件。我需要向树中添加搜索并仅显示其中包含搜索词的那些节点/叶子。但是,我似乎无法弄清楚如何实现这一目标。有人可以帮帮我吗?

【问题讨论】:

【参考方案1】:

我不完全确定您的问题是否完全,但它应该给出提示。

让我们使用参考文档示例作为偏移量,有 1) 存储 2) 模型和 3) 树

    var store = new ItemFileReadStore(
        url: "dataUrl/dijit/tests/_data/countries.json"
    );

    var treeModel = new ForestStoreModel(
        store: store,
        query: "type": "continent", // note, this bit
        rootId: "root",
        rootLabel: "Continents",
        childrenAttrs: ["children"]
    );

    new Tree(
        model: treeModel
    , "treeOne");

如上解释;您已加载所有已知的国家和大洲,但“用户”已选择仅通过在模型上使用查询来显示大洲 - 然后层次结构以树结构表示。

你想要一个带有搜索功能的文本框,所以我们连接到 onChange

    new dijit.form.TextBox(
        onChange: function() 
              ...
        
    );

首先,获取变量

var searchByName = this.get("value");
var oQuery = treeModel.query;

接下来,在模型上设置一个新的查询 - 用一个对象 mixin 保留旧的查询

treeModel.query = dojo.mixin(oQuery,  name: '*'+searchByName+'*' );

最后,通知模型及其树发生了变化 - 并重新查询可见项。

treeModel._requeryTop();

NB 如果***项目(对于 ForestModel)不可见,则不会显示其子元素,即使搜索字符串与这些元素匹配。 (例如,如果查询不匹配美国大陆,则不显示阿拉巴马州)

编辑

由于 OP 有“NB”的议程,这可能无法 100% 满足需求,但它是 dojo 通过 dijit.Tree 提供的。因为将模型/存储查询重新编码为包括父分支直到 root 我不会在这里这样做 - 但仍然有一些技巧;)

var tree = new dijit.Tree( 
   /**
    * Since TreeNode has a getParent() method, this abstraction could be useful
    * It sets the dijit.reqistry id into the item-data, so one l8r can get parent items
    * which otherwise only can be found by iterating everything in store, looking for item in the parent.children
    *
   */
   onLoad : function() 
       this.forAllNodes(function(node) 
            // TreeNode.item <-- > store.items hookup
            node.item._NID = node.domNode.id
       );
   ,
   /* recursive iteration over TreeNode's
    * Carefull, not to make (too many) recursive calls in the callback function..
    * fun_ptr : function(TreeNode)  ... 
   */
   forAllNodes : function(parentTreeNode, fun_ptr) 
        parentTreeNode.getChildren().forEach(function(n) 
             fun_ptr(n);
             if(n.item.children) 
                 n.tree.forAllNodes(fun_ptr);
             
        )
   
);

(未经测试,但可能只是工作)示例:

// var 'tree' is your tree, extended with
tree.forAllNodes = function(parentTreeNode, fun_ptr) 
        parentTreeNode.getChildren().forEach(function(n) 
             fun_ptr(n);
             if(n.item.children) 
                 n.tree.forAllNodes(fun_ptr);
             
        )
;
// before anything, but the 'match-all' query, run this once
tree.forAllNodes(tree.rootNode, function(node) 
    // TreeNode.item <-- > store.items hookup
    node.item._NID = node.domNode.id
);

// hopefully, this in end contains top-level items
var branchesToShow = [] 

// run fetch every search (TextBox.onChange) with value in query
tree.model.store.fetch(query:name:'Abc*', onComplete(function(items) 
   var TreeNode = null;
   dojo.forEach(items, function(item) 
       TreeNode = dijit.byId(item._NID+'');
       while(TreeNode.getParent() 
             && typeof TreeNode.getParent().item._RI == 'undefined') 
          TreeNode = TreeNode.getParent();
       
       branchesToShow.push(TreeNode.item);
   );
);

// Now... If a success, try updating the model via following
tree.model.onChildrenChange(tree.model.root, branchesToShow);

【讨论】:

您好,感谢您的帮助!情况是,在我对树模型的原始定义中,我有“查询:“type”:“parent””,而在搜索时,我需要根据节点和叶子的名称获取查询。在当前情况下,当我按叶子的名称搜索时,它不会返回任何节点。 商店查询本身将返回结果.. 只是,树无法显示它们,因为它们的叶子分支已被“切断”,即更高级别的项目值与查询不匹配。您需要查询商店,然后手动迭代子节点以设置完整的分支可见/隐藏 它会变得相当混乱...模型没有双重链接项目,所以孩子们不知道他们的父母是谁 那么,这基本上是不可能的? 没有什么是不可能的 :p 但话虽如此,我建议使用相同的商店设置一个 FilteringSelect 输入字段 - 然后花费 3-4 小时加上该实现的编码。或制作store.fetch(query:namebasedonly:'??', onComplete:function(items) items...ids...tree...nodes..toggle highlight CSS if item match ); 功能

以上是关于在 dijit.Tree 中搜索的主要内容,如果未能解决你的问题,请参考以下文章

dijit.Tree 重新加载时不会崩溃

带有提交错误值的单选按钮的 Dijit.tree 扩展

dijit.tree 如何仅使用商店实现折叠所有功能?

Dojo - Dijit.Tree - 更新树

Error:dijit.tree.TreeStoreModel:root query returned 0 items

dojo组件使用---tree组件的局部更新