Pages

搜尋此網誌

2013年12月25日 星期三

extjs: tree 的建立與使用

extjs: tree 的建立與使用

資料來源:

ExtJS的TreePanel樹是繼承Ext.Panel,所以它可以算是一個Container,不過它也是算是一個ExtJS的Component,給於TreeNode來完成樹狀結果,可以應用在選單或是分類等地方。

這裡將介紹兩種 tree 的建立方式:

利用物件來產生 tree

Ext.onReady( function() {

    var root = new Ext.tree.TreeNode( {
        text : '根'
    });

    var node1Child1 = new Ext.tree.TreeNode( {
        text : '個人資料維護',
        leaf : 'true'// 是否為末結果,樹葉
    });
    var node1Child2 = new Ext.tree.TreeNode( {
        text : '密碼變更',
        leaf : 'true'// 是否為末結果,樹葉
    });

    var node1 = new Ext.tree.TreeNode( {
        text : '個人資料'
    });
    node1.appendChild(node1Child1);
    node1.appendChild(node1Child2);

    root.appendChild(node1);

    var viewport = new Ext.tree.TreePanel( {

        title : "系統相關",
        width : 200,

        height : 500,
        rootVisible : true,//root結點顯不顯示
        root : root

    });

    viewport.render('toolbar');
    viewport.doLayout();

});

利用 script 來產生 tree 透過 AsyncTreeNode

若是用此方法需要使用 AsyncTreeNode,此外你的 children 也可以掛載 json Object 需要注意的是組成 tree 所需要的 config 都需要有才能正確產生,以及 AsyncTreeNode 的特性,如果節點一次都沒有打開過,若想要經由 findChild來取得參照是沒辦法的,因為是 Async (非同步),所以未開啟其節點尚未實體化。

Ext.onReady( function() {
    var viewport = new Ext.tree.TreePanel( {

        title : "系統相關",
        width : 200,

        height : 500,
        rootVisible : true,//root結點顯不顯示
        root : new Ext.tree.AsyncTreeNode( {
            text : '根',

            children : [ {
                text : '個人資料',
                children : [ {
                    text : '個人資料維護',
                    leaf : true
                }, {
                    text : '密碼變更',
                    leaf : true
                } ]
            }, {
                text : '客戶資料',
                children : [ {
                    text : '客戶基本資料查詢維護',
                    leaf : true
                }, {
                    text : '客戶基本資料列印',
                    leaf : true
                } ]
            }]
        })

    });

    viewport.render('toolbar');
    viewport.doLayout();

});

讀取 json 資料來源產生 tree

假設遠端的 json 資料來源:

[{
    id: 1,
    text: 'A leaf Node',
    leaf: true
},{
    id: 2,
    text: 'A folder Node',
    children: [{
        id: 3,
        text: 'A child Node',
        leaf: true
    }]
}]

leaf 屬性會在 load 的時候,判斷是否要在遞迴產生子節點。而原本的 Ext.tree.TreeNode 並不支援 Ajax,所以也要改成 Ext.tree.AsyncTreeNode,程式碼如下:

Ext.onReady(function() {
    var root = new Ext.tree.AsyncTreeNode({text: 'root'});
    var tree = new Ext.tree.TreePanel({
        el: 't',
        width: 150,
        autoHeight: true,
        root: root,
        loader: new Ext.tree.TreeLoader({dataUrl: 'tree.json'})
    });
    tree.render();
});

與上面的例子差別在多了使用了 Ext.tree.TreeLoader。

讀取 xml 資料來源產生 tree

除了 json 結構讀取外,在 extjs 的 官方 sample 有資料來源為 xml 的範例。

其中使用 extjs 延伸套件 Ext.ux.tree.XmlTreeLoader,使用上必須先自行定義 component extend Ext.ux.tree.XmlTreeLoader 並且實作 processAttributes,使用上無法定義 maping 的方式,他會把所有的 xml tag 跑過一變,必須在 tag 中的 Attribute 能有識別的方式,其中若是 tag 裡的內容預設會塞入 innerText 參數。

tree 的操作與參照

上面介紹了各種產生 tree 的方式,這邊要介紹一下如何透過 extjs 提供的函數來操作相關的節點,幾個重要的函數:

  • expandPath( path, [attr], [callback] )

    預設的 path 是根據 id 來作為目錄結構的敘述,[attr] 可以改變目錄索引的屬性。

  • selectPath( path, [attr], [callback] )

    使用方式同上,不同的是會執行 expandPath 在做 selectPath

  • findChild( attribute, value, [deep] )

    用來查詢特定的節點,其中若未設置 deep = tree 將只搜尋使用此函數之物件的下一層,另外在上面有提到,如果是使用 AsyncTreeNode 尚未開啟節點前是找不到的。

其他請參照 API,以下有實際使用飯例:

Ext.onReady( function() {
  var viewport = new Ext.tree.TreePanel( {
    title : "系統相關",
    width : 200,
    height : 500,
    rootVisible : true,//root結點顯不顯示
    root : new Ext.tree.AsyncTreeNode( {
      text : '根',
      id:'r',

      children : [ {
        text : '個人資料',
        id:'c1',
        children : [ {
            text : '個人資料維護',
            id:'c1c1',
            leaf : true

        }, {
            text : '密碼變更',
            myid:'c1c2',
            leaf : true
        } ]
      }, {
        text : '客戶資料',
        id:'c2',
        children : [ {
            text : '客戶基本資料查詢維護',
            leaf : true,
            id:'c2c1'
        }, {
            text : '客戶基本資料列印',
            leaf : true,
            id:'c2c2'
        } ]
      } ]
    })

  });

  viewport.render('toolbar');
  viewport.doLayout();

  var btn=new Ext.Button({
    renderTo:"btn",
    id:'test',
    text:'test',
    handler:function(){

        // selectPath 可以做到 expand 之後在進行 select
      viewport.selectPath('/r/c2/c2c1');

      // 選取另一個節點需注意的是若 c1c1 此節點未被開啟,結果會為 undifine
      alert(viewport.root.findChild( 'id', 'c1c1', true ));

      // 一旦開啟過節點,再次 findChild 就會取得實體。
      viewport.expandPath('/r/c1/c1c1');
      alert(viewport.root.findChild( 'id', 'c1c1', true ));

      // 除了 id 之外,我們也可以用別的屬性來做搜尋
      viewport.root.findChild( 'myid', 'c1c2', true ).select();
    }
  });

});

說明都在程式註解中,這邊就不再多做說明,以下是實際範例運行的結果:

張貼留言