103

JSF2アプリケーションでPrimefacesを使用しています。があり<p:dataTable>、行を選択する代わりに、ユーザーが個々の行に対してさまざまなアクションを直接実行できるようにしたいと考えています。<p:commandLink>そのために、最後の列にいくつかのがあります。

私の問題:どの行を操作するかを知るために、コマンドリンクによって開始されたアクションに行IDを渡すにはどうすればよいですか?私は<f:attribute>:を使用してみました

<p:dataTable value="#{bean.items}" var="item">
    ...
    <p:column>
        <p:commandLink actionListener="#{bean.insert}" value="insert">
            <f:attribute name="id" value="#{item.id}" />
        </p:commandLink>
    </p:column>
</p:dataTable>

fただし、常に0になります。属性がレンダリングされるときに行変数は使用できないようです(固定値を使用すると機能します)。

誰かが別の解決策を持っていますか?

4

4 に答える 4

216

原因に関しては、<f:attribute>はコンポーネント自体に固有であり(ビューのビルド時に入力されます)、反復された行(ビューのレンダリング時に入力されます)ではありません。

要件を達成するには、いくつかの方法があります。

  1. サーブレットコンテナが最小のサーブレット3.0/EL 2.2をサポートしている場合は、それをUICommand コンポーネントまたはAjaxBehaviorタグのアクション/リスナーメソッドの引数として渡すだけです。例えば

     <h:commandLink action="#{bean.insert(item.id)}" value="insert" />
    

    と組み合わせて:

     public void insert(Long id) {
         // ...
     }
    

    これには、フォーム送信要求のためにデータモデルが保持されている必要があるだけです。最良の方法は、Beanをビュースコープに配置すること@ViewScopedです。

    アイテムオブジェクト全体を渡すこともできます。

     <h:commandLink action="#{bean.insert(item)}" value="insert" />
    

    と:

     public void insert(Item item) {
         // ...
     }
    

    サーブレット2.5コンテナでは、JBoss ELのように、これをサポートするEL実装を提供する場合にもこれが可能です。構成の詳細については、この回答を参照してください。


  2. コンポーネントで使用<f:param>UICommandます。リクエストパラメータを追加します。

     <h:commandLink action="#{bean.insert}" value="insert">
         <f:param name="id" value="#{item.id}" />
     </h:commandLink>
    

    Beanがリクエストスコープの場合、JSFに設定させます@ManagedProperty

     @ManagedProperty(value="#{param.id}")
     private Long id; // +setter
    

    または、Beanのスコープが広い場合、またはよりきめ細かい検証/変換が必要な場合<f:viewParam>は、ターゲットビューで使用します。f:viewParamと@ManagedPropertyも参照してください。

     <f:viewParam name="id" value="#{bean.id}" required="true" />
    

    いずれにせよ、これには、フォーム送信のためにデータモデルを必ずしも保持する必要がないという利点があります(Beanがリクエストスコープの場合)。


  3. コンポーネントで使用<f:setPropertyActionListener>UICommandます。利点は、Beanのスコープがリクエストスコープよりも広い場合に、リクエストパラメータマップにアクセスする必要がなくなることです。

     <h:commandLink action="#{bean.insert}" value="insert">
         <f:setPropertyActionListener target="#{bean.id}" value="#{item.id}" />
     </h:commandLink>
    

    と組み合わせて

     private Long id; // +setter
    

    idこれは、アクションメソッドのプロパティによってのみ使用可能になります。これには、フォーム送信要求のためにデータモデルが保持されている必要があるだけです。最良の方法は、Beanをビュースコープに配置すること@ViewScopedです。


  4. 代わりに、データテーブルの値をにバインドしDataModel<E>ます。これにより、アイテムがラップされます。

     <h:dataTable value="#{bean.model}" var="item">
    

     private transient DataModel<Item> model;
    
     public DataModel<Item> getModel() {
         if (model == null) {
             model = new ListDataModel<Item>(items);
         }
         return model;
     }
    

    (実装されていないtransientため、ビューまたはセッションスコープのBeanでこれを使用する場合は、ゲッターで作成して遅延インスタンス化する必要があります)DataModelSerializable

    そうすれば、何も渡さずに現在の行にアクセスできるようになりますDataModel#getRowData()(JSFは、クリックされたコマンドリンク/ボタンの要求パラメーター名に基づいて行を決定します)。

     public void insert() {
         Item item = model.getRowData();
         Long id = item.getId();
         // ...
     }
    

    これには、フォーム送信リクエスト用にデータモデルを保持する必要もあります。最良の方法は、Beanをビュースコープに配置すること@ViewScopedです。


  5. Application#evaluateExpressionGet()プログラムで現在を評価するために使用します#{item}

     public void insert() {
         FacesContext context = FacesContext.getCurrentInstance();
         Item item = context.getApplication().evaluateExpressionGet(context, "#{item}", Item.class);
         Long id = item.getId();
         // ...
     }
    

どちらを選択するかは、機能要件と、どちらかが他の目的により多くの利点を提供するかどうかによって異なります。個人的には#1を使用しますが、サーブレット2.5コンテナもサポートしたい場合は、#2を使用します。

于 2011-02-14T16:54:55.087 に答える
11

JSF 1.2では、これは<f:setPropertyActionListener>(コマンドコンポーネント内で)によって行われました。JSF 2.0(正確には、BalusCのおかげでEL 2.2)では、次のように実行できます。action="${filterList.insert(f.id)}

于 2011-02-14T16:48:50.327 に答える
11

私のビューページ:

<p:dataTable  ...>
<p:column>
<p:commandLink actionListener="#{inquirySOController.viewDetail}" 
               process="@this" update=":mainform:dialog_content"
           oncomplete="dlg2.show()">
    <h:graphicImage library="images" name="view.png"/>
    <f:param name="trxNo" value="#{item.map['trxNo']}"/>
</p:commandLink>
</p:column>
</p:dataTable>

バッキングビーン

 public void viewDetail(ActionEvent e) {

    String trxNo = getFacesContext().getRequestParameterMap().get("trxNo");

    for (DTO item : list) {
        if (item.get("trxNo").toString().equals(trxNo)) {
            System.out.println(trxNo);
            setSelectedItem(item);
            break;
        }
    }
}
于 2011-05-09T08:50:05.373 に答える
0

Mkyongによるこのサイトのおかげで、パラメータを渡すために実際に機能した唯一のソリューションはこれでした

<h:commandLink action="#{user.editAction}">
    <f:param name="myId" value="#{param.id}" />
</h:commandLink>

public String editAction() {

  Map<String,String> params = 
            FacesContext.getExternalContext().getRequestParameterMap();
  String idString = params.get("myId");
  long id = Long.parseLong(idString);
  ...
}

技術的には、メソッド自体に直接渡すことはできませんが、に渡すことができますJSF request parameter map

于 2015-04-20T20:21:10.753 に答える