2

同様の質問をたくさん読みましたが、問題を解決する方法がわかりません。

ビュースコープの自己完結型のマネージドBeanに裏打ちされた複合コンポーネントを作成しました。
コンポーネントは、ダイアログを開くボタンを備えたオートコンプリートテキストボックスで構成されています。ユーザーは、名前(オートコンプリート)またはツリー内のノードの選択(ダイアログ)のいずれかでアイテムを選択できます。
バッキングBeanは、必要なすべてのもの(データアクセス、ツリーロジックなど)を実装し、選択したアイテムを(POJOとして)公開する必要があります。

今私は2つの問題があります:

  1. ツリー管理は複雑であるため、selectedObjプロパティは、Beanでいくつかの処理を行うゲッターとセッターによってアクセスされます。これらは単にクラスフィールドにアクセスするだけではありません。これで、Bean全体を属性として渡します。selectedObjBeanの複合コンポーネントの「値」属性を作成するにはどうすればよいですか?

  2. 同じビューでコンポーネントの複数のインスタンスを使用するにはどうすればよいですか?

コンポーネントの例を次に示します。

<cc:interface>
    <cc:attribute name="bean" type="com.yankee.OUTreeBean" required="true"/>
    <cc:attribute name="listener" method-signature="void listener()"/>
</cc:interface>
<cc:implementation>
    <p:dialog id="#{cc.id}_dialog" widgetVar="_dlg" header="Select OU" modal="true" dynamic="true" >
        <p:toolbar>
            <!-- some buttons to refresh, expand, collapse etc. -->
        </p:toolbar>
        <p:tree id="#{cc.id}_tree" value="#{cc.attrs.bean.root}" var="node"
                selectionMode="single"
                selection="#{cc.attrs.bean.selectedNode}">
            <p:ajax event="select" update="@form" listener="#{cc.attrs.listener}" oncomplete="if (!args.validationFailed) _dlg.hide()" />
            <p:treeNode>  
                <h:outputText value="#{node.OU_NAME}" />  
            </p:treeNode>  
        </p:tree>
    </p:dialog>

    <p:autoComplete id="#{cc.id}_inner" value="#{cc.attrs.bean.selectedObj}" completeMethod="#{cc.attrs.bean.completeObj}"  
                    var="obj" itemLabel="#{obj.OU_NAME}" itemValue="#{obj}" 
                    forceSelection="true" 
                    converter="ouConverter"
                    multiple="false" 
                    minQueryLength="2">
        <p:ajax event="itemSelect" listener="#{cc.attrs.listener}" update="@form"/>
    </p:autoComplete>
    <div style="float: right">
        <p:commandButton id="bSearch" icon="ui-icon-search" onclick="_dlg.show()"/>
    </div>
</cc:implementation>

コンポーネントのバッキングBean:

@ManagedBean
@ViewScoped
public class OUTreeBean implements Serializable {
    private static final long serialVersionUID = 1L;

    private List<OU> data;  // Data as plain list
    protected TreeNode root;  // root node of data as a tree
    protected TreeNode selectedNode;

    @PostConstruct
    private void init() throws SQLException {
        refreshData();
    }

    public OU getSelectedObj() {
        if (selectedNode == null) {
            return null;
        }
        return ((OU) selectedNode.getData());

    }
    public void setSelectedObj(OU ou) {
        // Find the right tree node and do whatever needed
    }
    public TreeNode selectedNode getSelectedNode() {
        // Blah blah
    }
    public void setSelectedNode(TreeNode selectedNode) {
        // Blah blah
    }
    public List<OU> completeObj(String namePattern) {
        // Autocomplete handler
    }
    public void refreshData() {
        // Blah blah
    }
    // etc...

}

使用ページの抜粋:

<ism:selectOUTree id="cbSelectOu" bean="#{myBean.ouFilterBean}" listener="#{myBean.onOUChange}"/>

PAGEのバッキングBean:

@ManagedBean
@ViewScoped
public class MyBean implements Serializable {

    private static final long serialVersionUID = 1L;
    @ManagedProperty("#{oUTreeBean}")
    private OUTreeBean ouFilterBean;

    public void onOUChange() throws SQLException {
        // Blah blah
    }
}
4

1 に答える 1

1

私は数日前に同じ問題を抱えていました。あなたと同じように、私ManagedBeanは仕事をするべきオブジェクトとして使用しました。しばらくして、 を作成するだけでよいことがわかりましたFacesComponent。私はJSFが初めてなので、解決策を見つけるのは簡単ではありませんでしたが、すべての問題を解決しました。これはどのように機能しますか:

view.xhtml

<h:body>
    <cc:interface componentType="playerComponent">
        <cc:attribute name="playerId" required="true"/>
    </cc:interface>
    <cc:implementation>
        <c:set var="inplaceId" value="inplace-#{cc.attrs.playerId}" />
        <c:set var="outputId" value="output-#{cc.attrs.playerId}" />
        <h:form id="form-#{cc.attrs.playerId}">
            <p:inplace editor="false" widgetVar="#{inplaceId}">
                <h:inputText value="#{cc.player.name}" id="outputId"/>
                <p:commandButton onclick="#{inplaceId}.save()" action="#{cc.save}" update="#{outputId}" value="save" />
                <p:commandButton onclick="#{inplaceId}.cancel()" update="#{outputId}" value="cancel"  />
            </p:inplace>
        </h:form>
    </cc:implementation>
</h:body>

PlayerComponent.java

@FacesComponent("playerComponent")
public class PlayerComponent extends UINamingContainer {

    private Player player;

    private void init() {
        Object idObj = getAttributes().get("playerId");
        if (idObj != null) {
            // create player object
        }
    }

    public void save() {
        // save player object
    }

    public Player getPlayer() {
        if (player == null) {
            init();
        }
        return player
    }
}

Player.java (エンティティ)

public class Player {
    private name;
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

私が書いたように、私はJSFの初心者であり、おそらくプレーヤーオブジェクトは別の方法で作成する必要があります(@PostConstructコンストラクターで on を使用しますか?)が、これは機能します。

于 2013-02-27T18:39:39.723 に答える