0

Primefaces の ap:selectOneMenu コンポーネント (ドロップダウン リスト) から値を選択したい。Java Bean からデータを取得します。次のコードがあります。

XHTML:

<!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:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
<h:body>
    <h:form>
        <p:messages id="errorMessages" style="color:red;margin:8px;" />
        <br></br>

        <p:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">

            <h:outputText value="Tasks: "/>
            <p:selectOneMenu value="#{devTestController.selectedTask}">
                <f:selectItems value="#{devTestController.tasks}" var="task" itemLabel="#{task.label}" itemValue="#{task.value}"/>
                <f:converter converterId="infoRowBeanConverter" />
            </p:selectOneMenu>

        </p:panelGrid>

        <br/>
        <p:commandButton value="Execute Task" update = "errorMessages" action="#{devTestController.executeTask()}"/>


    </h:form>

</h:body>
</html>

Java Bean DevTestController.java:

package mypackage;

import java.util.LinkedList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;

@ManagedBean
@RequestScoped
public class DevTestController
{
    private InfoRowBean              selectedTask;
    private static List<InfoRowBean> tasks;

    @PostConstruct
    public void initList()
    {
        if (tasks == null)
        {
            tasks = new LinkedList<>();
            tasks.add(new InfoRowBean("Task 1", "Task 1"));
            tasks.add(new InfoRowBean("Task 2", "Task 2"));
        }
    }

    public InfoRowBean getSelectedTask()
    {
        return selectedTask;
    }

    public void setSelectedTask(InfoRowBean selectedTask)
    {
        this.selectedTask = selectedTask;
    }

    public List<InfoRowBean> getTasks()
    {
        return tasks;
    }

    public void executeTask()
    {
        System.out.println("Executing task " + selectedTask.label);
    }

}

InfoRowBean.java:

package mypackage;

import java.util.List;

public class InfoRowBean
{
    String label = null;
    String value = null;

    public InfoRowBean(String label, String value)
    {
        setLabel(label);
        setValue(value);
    }

    public String getLabel()
    {
        return label;
    }

    public void setLabel(String label)
    {
        this.label = label;
    }

    public String getValue()
    {
        return value;
    }

    public void setValue(String value)
    {
        this.value = value;
    }

    // This must return true for another InfoRowBean object with same label/id.
    public boolean equals(Object other)
    {
        return other instanceof InfoRowBean && (label != null) ? label.equals(((InfoRowBean) other).label) : (other == this);
    }

    // This must return the same hashcode for every InfoRowBean object with the same label.
    public int hashCode()
    {
        return label != null ? this.getClass().hashCode() + label.hashCode() : super.hashCode();
    }

    // Override Object#toString() so that it returns a human readable String representation.
    // It is not required by the Converter or so, it just pleases the reading in the logs.
    public String toString()
    {
        return "InfoRowBean[" + label + "," + value + "]";
    }

}

コンバータ InfoRowBeanConverter.java:

package mypackage;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;

@FacesConverter("infoRowBeanConverter")
public class InfoRowBeanConverter implements Converter
{

    public Object getAsObject(FacesContext context, UIComponent component, String value)
    {
        return value;
    }

    public String getAsString(FacesContext context, UIComponent component, Object value)
    {
        return value.toString();
    }

}

ボタンを押しても何も起こりません(エラーもありません)。タグからパラメーター「値」を削除すると(つまり、 leave )、ボタンは正常に機能しますが、もちろん、選択したアイテムを取得できません。ここで何が問題なのですか?

4

1 に答える 1

2

問題は、コンバーターがメソッドで送信された文字列値を具体的なInfoRowBeanインスタンスに変換せず、メソッドで生成した生の送信値をgetAsObject()返すことです。これは の型と一致しません。これはです。StringgetAsString()selectedTaskInfoRowBean

通常はデータベース識別子のフレーバーで、複雑なオブジェクトの一意の文字列表現を返すようにコンバーターを適切に修正する必要がありgetAsString()ます (HTML 出力や HTTP 要求パラメーターなどのテキストベースの形式でさらに使用できるようにするため)。そしてgetAsObject()、通常は一意の識別子をキーとして使用するDB呼び出しを介して、その一意の文字列表現を具体的な複合オブジェクトインスタンスに正確に変換します。

別の方法はomnifaces.SelectItemsConverterJSF ユーティリティ ライブラリ OmniFaces<f:selectItem(s)>を使用することです。これにより、複雑なオブジェクトを値として使用するコンポーネントのカスタム コンバーターを作成する必要がなくなります。

もう 1 つの方法は、beの代わりに変更selectedTaskすることです(この構成ではまったく役に立たないため、コンバーター全体を削除します)。StringInfoRowBean

以下も参照してください。

于 2013-09-24T14:18:09.540 に答える