かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

RichFaces 4.2.xのtreeコンポーネントの基本的な使い方

毎回調べるのもあれなので個人的なメモ。

pom.xmlにrichfacesを追加

<dependency>
    <groupId>org.richfaces.ui</groupId>
    <artifactId>richfaces-components-ui</artifactId>
    <version>${richfaces.version}</version>
</dependency>
<dependency>
    <groupId>org.richfaces.core</groupId>
    <artifactId>richfaces-core-impl</artifactId>
    <version>${richfaces.version}</version>
</dependency>

${richfaces.version}はpropertiesタグのところで定義してる。ここでは現時点で最新の4.2.3.Final。

<properties>
    ...省略...
    <richfaces.version>4.2.3.Final</richfaces.version>
</properties>

ツリーに紐づけるオブジェクトの作成

ここは何でもいい。とりあえず、以下のようなツリー構造をもつItemというクラスを作りました。

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package okazuki.mavenproject4;

import java.util.Arrays;
import java.util.List;

public class Item {

    private String text;
    private List<Item> items;

    public Item() {
    }

    public Item(String text, Item... items) {
        this.text = text;
        this.items = Arrays.asList(items);
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public List<Item> getItems() {
        return items;
    }

    public void setItems(List<Item> items) {
        this.items = items;
    }
}

treeコントロールのノードのクラスを作成

さっきのItemクラスをさくっと再利用できればいいのですが、どうもTreeNodeインターフェース実装してないとダメそうなので…。TreeNodeImpleという実装済みクラスがあるので、これを継承してItemクラスを内部に持つItemTreeNodeクラスを作ります。

class ItemTreeNode extends TreeNodeImpl {

    private Item item;

    // ItemからTreeNodeを組み立てる
    public ItemTreeNode(Item item) {
        this.item = item;
        if (item.getItems() == null) {
            return;
        }
        if (!item.getItems().isEmpty()) {
            int index = 0;
            for (Item i : item.getItems()) {
                // addChildの第一引数は、要素を一意に識別できるものであればいい
                this.addChild(index++, new ItemTreeNode(i));
            }
        }
    }
    
    // とりあえず簡易的にtoStringの結果を表示するように
    @Override
    public String toString() {
        return item.getText();
    }

    // 子要素を持ってなかったら葉
    @Override
    public boolean isLeaf() {
        if (item.getItems() == null) {
            return true;
        }
        return item.getItems().isEmpty();
    }
}

ManagedBeanでTreeNodeのプロパティを公開

適当にManagedBeanを作ってtreeコントロールに紐づけるためのTreeNode型のプロパティを作ります。ここではIndexPageというManagedBeanにrootという名前でプロパティを作りました。

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package okazuki.mavenproject4;

import java.util.Arrays;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import org.richfaces.model.TreeNode;
import org.richfaces.model.TreeNodeImpl;

/**
 *
 * @author Kazuki
 */
@ManagedBean
@RequestScoped
public class IndexPage {

    private TreeNode root;

    ...省略...

    public TreeNode getRoot() {
        return root;
    }

    public void setRoot(TreeNode root) {
        this.root = root;
    }
}

あとは、要件に応じて適切なタイミングでrootプロパティにTreeNodeをセットします。とりあえず、今回はコンストラクタでさくっと作りました。気を付けないといけないのは、TreeNodeのルートは、画面に表示されないっぽい?というところです。

public IndexPage() {
    // Itemクラスを適当に組み立てる
    List<Item> items = Arrays.asList(
            new Item("item1",
                new Item("item1-1"),
                new Item("item1-2"),
                new Item("item1-3",
                    new Item("item1-3-1"),
                    new Item("item1-3-2"))),
            new Item("item2",
                new Item("item2-1"),
                new Item("item2-2")),
            new Item("item3",
                new Item("item3-1"),
                new Item("item3-2")),
            new Item("item4",
                new Item("item4-1")),
            new Item("item5"));

    // rootは表示されないっぽい?
    this.root = new TreeNodeImpl(false);
    // rootの下に子をぶら下げていく
    int index = 0;
    for (Item item : items) {
        this.root.addChild(index++, new ItemTreeNode(item));
    }
}

画面のマークアップ

あとは、画面にtreeコントロール置いてやるだけです。treeコントロールを置いてtreeNodeを中に置いて、どうやって表示するか定義します。

<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
      xmlns:rich="http://richfaces.org/rich">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <rich:tree value="#{indexPage.root}" var="item" toggleType="client">
            <rich:treeNode>
                <!-- itemはItemTreeNodeクラス -->
                <h:outputText value="#{item}" />
            </rich:treeNode>
        </rich:tree>
    </h:body>
</html>

treeNodeは、もうちょっと色々カスタマイズできるみたいだけど、とりあえず基本はこんな感じで。toggleType="client"でクライアントサイドでツリーの展開とかやるってことみたいですわ。

実行結果