かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

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"でクライアントサイドでツリーの展開とかやるってことみたいですわ。

実行結果