2013-08-31 5 views
12

問題は、最初のページでいくつかの項目を選択した後、別のページにページを戻して戻ってくると、私の初期選択が表示されません。私はSelectableDataModelと同様にrowKey属性を実装しようとしましたが、問題は解決しません。p:LazyDataModelを改ページした後にdataTableの選択が失われる

これは私のテストBeanです:

@ManagedBean 
@ViewScoped 
public class MrBean { 
    private List<Item> chosenItems; 
    private LazyDataModel lazyModel; 

    @PostConstruct 
    public void prepareTest() { 
     this.lazyModel = new LazyItemDataModel(); 
    } 

    public void countItems() { 
     System.out.println("TEST 3: chosenItems's size: " + chosenItems.size()); 
    } 

    private class LazyItemDataModel extends LazyDataModel<Item> implements SelectableDataModel<Item> { 
     @Override 
     public Item getRowData(String rowKey) { 
      System.out.println("TEST 1: getRowData"); 
      Iterator<Item> iter = ((List<Item>) this.getWrappedData()).iterator(); 
      while (iter.hasNext()) { 
       Item item = iter.next(); 
       if (item.getId().equals(rowKey)) { 
        return item; 
       } 
      } 

      return null; 
     } 

     @Override 
     public Object getRowKey(Item item) { 
      return item.getId(); 
     } 

     @Override 
     public List<Item> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map filters) { 
      System.out.println("TEST 2: load"); 
      // Code to retrieve items from database 
     } 
    } 

    // Getters and Setters 
} 

これは私のテストページです:

<?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:p="http://primefaces.org/ui"> 
    <h:head> 
     <title>Test page</title> 
    </h:head> 
    <h:body> 
     <h:form> 
      <p:dataTable id="itemTable" var="item" value="#{mrBean.items}" rows="5" 
         paginator="true" selection="#{mrBean.chosenItems}" lazy="true" > 

       <p:ajax event="rowSelectCheckbox" listener="mrBean.countItems" />      

       <p:column selectionMode="multiple" /> 

       <p:column headerText="ID"> 
        <h:outputText value="#{item.id}" /> 
       </p:column> 

       <p:column headerText="Name"> 
        <h:outputText value="#{item.name}" /> 
       </p:column> 

      </p:dataTable> 
     </h:form> 
    </h:body> 
</html> 

あなたは私がここで間違って何をやったか私を見ることができれば、私は非常に感謝されると思います。

UPDATE:コンソールで

  1. 、私はページ付けするたびに、TEST 1: getRowData常にTEST 2: load前に印刷されています。私は上記のコードに多くのSystem.out.println("TEST")を追加した後は、私は次のことを観察しました。その結果、方法#LazyDataModel.getWrappedData()は古いページからデータを返す可能性があります。最初は、このメソッドの目的は、テーブル上で強調表示するために選択した行を取得することだと思いました。しかし、このメソッドがloadの前に呼び出されていれば、それは仕事を正しく行う方法はありませんか?
  2. 最初のページで2番目の項目を選択した後、コンソールでTEST 3: chosenItems's size: 2が表示されました。 2ページ目に改ページしてから1ページ目に戻った場合は、前述のように選択が失われます。しかし、別のアイテムを選択し続けると、コンソールでTEST 3: chosenItems's size: 3が表示されました。明らかに、chosenItemsのリストはまだ私の古い選択を保持しましたが、テーブルには表示されません。
+0

+1シンプルでテスト可能なSSCCEを提供します;-)次回Copy'paste'runにするために 'Item'サブクラスを追加することを検討してください –

+0

具体的な問題についてはわかりません。あなたのbeanはビュースコープですが、確かにページに戻ったときにすべてのプロパティをデフォルトに設定して再作成する必要がありますか?同じビューを操作する場合は、別のビューに移動するのではなく、同じビューで結果を条件付きでレンダリングすることを検討する必要があります。 – BalusC

+0

@BalusC私は彼が他のページに移動することについて話すとき、彼は実際にはビューの代わりにテーブルページ(ページング)を意味すると考えています。 –

答えて

0

私のデータテーブルにも同じ問題がありました。 selectBooleanCheckboxを代わりに使用しているため、私のケースは少し異なります。私は私のために働く簡単な解決策を見つけました。あなたが「古い選択がテーブルに表示されていない」と言ったとき、私はヒットしました。

  • a4jでチェックボックスをストラップ:サポートイベント

コード:

<h:selectBooleanCheckbox value="#{batch.toPortfolio}"> 
    <a4j:support event="onchange" /> 
</h:selectBooleanCheckbox> 
1

SelectionFeatureがデコードされたときに、新しいリストが作成されるためです。

そしてtable.getRowData(rowKeys[i])場合は(あなたのLazyDataModel実装に関連する)前ページでヌル古い選択があなたのLazyDataModelの実装を変更することによって、それを解決しようとするgone.mayされている返す私はこれらを試してみたがthisthisを見ていませんでした

LazyDataModelを実装するテーブルがたくさんある場合、同じ問題がありました。このソリューションは簡単だと思います。

これは私がやったことです:最初に怠惰であるかどうかをチェックしてから、現在選択されている行をselectionListに追加します。

プライムフェイス用4。0

1)DataTableRendererにおいて

面-config.xmlの

<render-kit> 
    <renderer> 
     <component-family>org.primefaces.component</component-family> 
     <renderer-type>org.primefaces.component.DataTableRenderer</renderer-type> 
     <renderer-class>com.package.LazyDataTableRenderer</renderer-class> 
    </renderer> 
</render-kit> 

そして

public class LazyDataTableRenderer extends DataTableRenderer { 
static Map<DataTableFeatureKey,DataTableFeature> FEATURES; 

    static { 
     FEATURES = new HashMap<DataTableFeatureKey,DataTableFeature>(); 
     FEATURES.put(DataTableFeatureKey.DRAGGABLE_COLUMNS, new DraggableColumnsFeature()); 
     FEATURES.put(DataTableFeatureKey.FILTER, new FilterFeature()); 
     FEATURES.put(DataTableFeatureKey.PAGE, new PageFeature()); 
     FEATURES.put(DataTableFeatureKey.SORT, new SortFeature()); 
     FEATURES.put(DataTableFeatureKey.RESIZABLE_COLUMNS, new ResizableColumnsFeature()); 
     FEATURES.put(DataTableFeatureKey.SELECT, new LazySelectionFeature()); 
     FEATURES.put(DataTableFeatureKey.ROW_EDIT, new RowEditFeature()); 
     FEATURES.put(DataTableFeatureKey.CELL_EDIT, new CellEditFeature()); 
     FEATURES.put(DataTableFeatureKey.ROW_EXPAND, new RowExpandFeature()); 
     FEATURES.put(DataTableFeatureKey.SCROLL, new ScrollFeature()); 
    } 

    @Override 
    public void decode(FacesContext context, UIComponent component) { 
     DataTable table = (DataTable) component; 

     for(Iterator<DataTableFeature> it = FEATURES.values().iterator(); it.hasNext();) { 
      DataTableFeature feature = it.next(); 

      if(feature.shouldDecode(context, table)) { 
       feature.decode(context, table); 
      } 
     } 

     decodeBehaviors(context, component);   
    } 
} 

2)SelectionFeatureのデコードオーバーライドをオーバーライド

を更新:

public class LazySelectionFeature extends org.primefaces.component.datatable.feature.SelectionFeature{ 

    @Override 
    public void decode(FacesContext context, DataTable table) { 
     String clientId = table.getClientId(context); 
     Map<String,String> params = context.getExternalContext().getRequestParameterMap(); 

     String selection = params.get(clientId + "_selection"); 

     if(table.isSingleSelectionMode()) 
      decodeSingleSelection(table, selection); 
     else 
      decodeMultipleSelection(context, table, selection); 
    } 

    void decodeSingleSelection(DataTable table, String selection) { 
      if(ComponentUtils.isValueBlank(selection)) 
       table.setSelection(null); 
      else 
       table.setSelection(table.getRowData(selection)); 
     } 

    void decodeMultipleSelection(FacesContext context, DataTable table, String selection) { 
     Class<?> clazz = table.getValueExpression("selection").getType(context.getELContext()); 
     boolean isArray = clazz.isArray(); 

     if(!isArray && !List.class.isAssignableFrom(clazz)) { 
      throw new FacesException("Multiple selection reference must be an Array or a List for datatable " + table.getClientId()); 
     } 

     if(ComponentUtils.isValueBlank(selection)) { 
      if(isArray) { 
       table.setSelection(Array.newInstance(clazz.getComponentType(), 0)); 
      } 
      else { 
       table.setSelection(new ArrayList<Object>()); 
      } 
     } 
     else { 
      String[] rowKeys = selection.split(","); 
      List<Object> selectionList = new ArrayList<Object>(); 

      boolean lazy=table.isLazy(); 
      if (lazy) { 

      List<String> currentRowKeys = new ArrayList<String>(Arrays.asList(rowKeys)); 
      if (table.getSelection() != null) { 
       List<Object> alreadySelected = (List<Object>) table.getSelection(); 

       for (Object object : alreadySelected) {//For deselecting 
        Object rowKeyFromModel = table.getRowKeyFromModel(object); 
        if (currentRowKeys.contains(rowKeyFromModel)) { 
         selectionList.add(object); 
         currentRowKeys.remove(rowKeyFromModel); 
        } 
       }      
      } 
      for (String key : currentRowKeys) {//For selecting 
       Object rowData = table.getRowData(key); 
       if (rowData != null && !selectionList.contains(rowData)) { 
         selectionList.add(rowData); 
       } 
      } 

     }else{ 

       for(int i = 0; i < rowKeys.length; i++) { 
        Object rowData = table.getRowData(rowKeys[i]); 

        if(rowData != null) 
         selectionList.add(rowData); 
       } 

      } 

      if(isArray) { 
       Object selectionArray = Array.newInstance(clazz.getComponentType(), selectionList.size()); 
       table.setSelection(selectionList.toArray((Object[]) selectionArray)); 
      } 
      else { 
       table.setSelection(selectionList); 
      } 
     } 
    } 
} 

の選択を解除できるように編集された最善の解決策ではないかもしれないが、動作するはずです、もっと良い方法がある場合は私に知らせてください。これが誰かを助けることを望みます。

+0

Ceydaのソリューションは機能します。ページネーション後の選択を維持します。しかし、1つの問題があります。選択後、選択を解除することはできません - なぜですか? – Gilberto

+0

datatable.jsファイルの修正が必要だと思います。 – Gilberto

+0

@Gilbertoca _if(lazy)_部分の_for_の末尾にある 'if(rowData!= null &&!selectionList.contains(rowData))selectionList.add(rowData);'を 'if(rowData!= null) null){ \t if(!selectionList.contains(rowData)){selectionList.add(rowData);} \t else {selectionList.remove(rowData);} }私は正しく覚えていれば動作するはずです。それはしばらくして、コードやテスト環境がなくなったので、それが動作すれば私に知らせてください。私は答えを更新します。 – Ceyda

1

はちょうどこのようなデータテーブル(selection="#{pageBackingForm.selectedEntityList}")の選択プロパティにバインドされたプロパティを実装し、それが動作します:Webページで

private Map<Integer, List<Entity>> selectedEntityListMap = new Hashtable<>(); 

    public List<Entity> getSelectedEntityList() { 
     return selectedEntityListMap.get(getCurrentEntitySelectionPage()); 
    } 

    public void setSelectedEntityList(List<Entity> selectedEntityList) { 
     if (selectedEntityList == null) { 
      selectedEntityListMap.remove(getCurrentEntitySelectionPage()); 
      return; 
     } 

     selectedEntityListMap.put(getCurrentEntitySelectionPage(), selectedEntityList); 
    } 

    public Integer getCurrentEntitySelectionPage() { 
     DataTable dataTable = (DataTable) FacesContext.getCurrentInstance().getViewRoot().findComponent("formId:dataTableId"); 
     return dataTable.getPage(); 
    } 
1

だけのためのイベントを追加するときに、ページ切替:

<p:ajax event="page" listener="#{listingBean.updateSelected()}" /> 

でリストBeanは、単に選択したものを保存します:

private List<GInstance> selectedInstances; 
private List<GInstance> selectedInstancesSaved; 

public List<GdWFInstance> getSelectedInstances() 
{ 
    return selectedInstancesSaved; 
} 

public void setSelectedInstances(List<GdWFInstance> selectedInstances) 
{ 
    this.selectedInstances = selectedInstances; 
} 

public void updateSelected() 
{ 
    if (selectedInstances != null && !selectedInstances.isEmpty()) { 
     for (GInstance inst : lazyModel.getDatasource()) { 
      if (selectedInstances.contains(inst)) { 
       selectedInstancesSaved.add(inst); 
      } else { 
       selectedInstancesSaved.remove(inst); 
      } 
     } 
    } 
} 
+0

ありがとう、これは完璧に、シンプルかつ簡単に働いた:) –

関連する問題