[Solucao] PrimeFaces DataTable Problema Com Ordenacao e Selecao

2 respostas
E

O datatable do PrimeFaces tem um serio Problema quando se usa
Ordenacao com Selecao.

Quando se ordena uma coluna visualmente ela fica em ordem Porem
quando se seleciona uma linha dePois de se realizar a ordenacao ele
nao seleciona a linha correta. Somente visualmente que eh selecionado
a linha correta, Porem quando vamos utilizar o objeto selecionado
ele eh o objeto que estava naquele lugar antes da ordenacao.

Ou Seja, quando ordenamos soh acontece ordenacao visual
a fonte de Dados continua na ordem original selecionando erradamente a linha.

Para resolver isso basta fazer uma modificacao na classe DataHelper

pacote - org.primefaces.component.datatable
classe - DataHelper

Importe a biblioteca do primefaces e faca um pacote com o nome acima
Faca uma classe chamada DataHelper com esse codigo

/*
 * Copyright 2010 Prime Technology.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.primefaces.component.datatable;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.el.ValueExpression;
import javax.faces.component.UIColumn;
import javax.faces.component.UIComponent;
import javax.faces.component.UINamingContainer;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;
import org.primefaces.component.column.Column;
import org.primefaces.context.RequestContext;
import org.primefaces.event.SelectEvent;
import org.primefaces.event.UnselectEvent;
import org.primefaces.model.BeanPropertyComparator;
import org.primefaces.model.Cell;

class DataHelper {

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

		String firstParam = params.get(clientId + "_first");
		String rowsParam = params.get(clientId + "_rows");
		String pageParam = params.get(clientId + "_page");

		table.setFirst(Integer.valueOf(firstParam));
		table.setRows(Integer.valueOf(rowsParam));
		table.setPage(Integer.valueOf(pageParam));

        if(table.isLazy()) {
            table.loadLazyData();
        }
	}

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

		String sortKey = params.get(clientId + "_sortKey");
		boolean asc = Boolean.valueOf(params.get(clientId + "_sortDir"));
        Column sortColumn = null;

        for(Column column : table.getColumns()) {
            if(column.getClientId(context).equals(sortKey)) {
                sortColumn = column;
                break;
            }
        }

        //Reset state
		table.setFirst(0);
		table.setPage(1);

        if(table.isLazy()) {
            table.setSortField(resolveField(sortColumn.getValueExpression("sortBy")));
            table.setSortOrder(asc);

            table.loadLazyData();

        } else {
            List sortData = new ArrayList();
            List list = (List) table.getValue();
            sortData.addAll(list);
            Collections.sort(sortData, new BeanPropertyComparator(sortColumn, table.getVar(), asc));
            table.setRowIndex(-1);      //cleanup
            table.setValue(sortData);

        }
	}

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

        //Reset state
        table.setFirst(0);
        table.setPage(1);

        if(table.isLazy()) {
            Map<String,String> filters = new HashMap<String, String>();
            Map<String,Column> filterMap = table.getFilterMap();

            for(String filterName : filterMap.keySet()) {
                Column column = filterMap.get(filterName);
                String filterValue = params.get(filterName).toLowerCase();

                if(!isValueBlank(filterValue)) {
                    String filterField = resolveField(column.getValueExpression("filterBy"));

                    filters.put(filterField, filterValue);
                }
            }

            table.setFilters(filters);

            table.loadLazyData();

            //Metadata for callback
            if(table.isPaginator()) {
                RequestContext.getCurrentInstance().addCallbackParam("totalRecords", table.getRowCount());
            }

        }
        else {
            Map<String,Column> filterMap = table.getFilterMap();
            List filteredData = new ArrayList();
            table.setValue(null);	//Always work with user data

            String globalFilter = params.get(clientId + UINamingContainer.getSeparatorChar(context) + "globalFilter");
            boolean hasGlobalFilter = !isValueBlank(globalFilter);
            if(hasGlobalFilter) {
                globalFilter = globalFilter.toLowerCase();
            }

            for(int i = 0; i < table.getRowCount(); i++) {
                table.setRowIndex(i);
                boolean localMatch = true;
                boolean globalMatch = false;

                for(String filterName : filterMap.keySet()) {
                    Column column = filterMap.get(filterName);
                    String columnFilter = params.get(filterName).toLowerCase();
                    String columnValue = String.valueOf(column.getValueExpression("filterBy").getValue(context.getELContext()));

                    if(hasGlobalFilter && !globalMatch) {
                        if(columnValue != null && columnValue.toLowerCase().contains(globalFilter))
                            globalMatch = true;
                    }

                    if(isValueBlank(columnFilter)) {
                        localMatch = true;
                    }
                    else if(columnValue == null || !column.getFilterConstraint().applies(columnValue.toLowerCase(), columnFilter)) {
                        localMatch = false;
                        break;
                    }

                }

                boolean matches = localMatch;
                if(hasGlobalFilter) {
                    matches = localMatch && globalMatch;
                }

                if(matches) {
                    filteredData.add(table.getRowData());
                }
            }

            table.setRowIndex(-1);	//cleanup

            table.setValue(filteredData);

            //Metadata for callback
            if(table.isPaginator()) {
                RequestContext.getCurrentInstance().addCallbackParam("totalRecords", filteredData.size());
            }

        }

	}

    public boolean isValueBlank(String value) {
		if(value == null)
			return true;

		return value.trim().equals("");
	}

    void decodeSelection(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(table, selection);

        table.setRowIndex(-1);	//clean

        //Instant selection and unselection
        queueInstantSelectionEvent(context, table, clientId, params);

		table.setRowIndex(-1);	//clean
	}

    void queueInstantSelectionEvent(FacesContext context, DataTable table, String clientId, Map<String,String> params) {

		if(table.isInstantSelectionRequest(context)) {
            int selectedRowIndex = Integer.parseInt(params.get(clientId + "_instantSelectedRowIndex"));
            table.setRowIndex(selectedRowIndex);
            SelectEvent selectEvent = new SelectEvent(table, table.getRowData());
            selectEvent.setPhaseId(PhaseId.INVOKE_APPLICATION);
            table.queueEvent(selectEvent);
        }
        else if(table.isInstantUnselectionRequest(context)) {
            int unselectedRowIndex = Integer.parseInt(params.get(clientId + "_instantUnselectedRowIndex"));
            table.setRowIndex(unselectedRowIndex);
            UnselectEvent unselectEvent = new UnselectEvent(table, table.getRowData());
            unselectEvent.setPhaseId(PhaseId.INVOKE_APPLICATION);
            table.queueEvent(unselectEvent);
        }
	}

    void decodeSingleSelection(DataTable table, String selection) {
		if(isValueBlank(selection)) {
			table.setSelection(null);
            table.setEmptySelected(true);
		} else {
            if(table.isCellSelection()) {
				table.setSelection(buildCell(table, selection));
			}
            else {
                table.setRowIndex(Integer.parseInt(selection));
                Object data = table.getRowData();

                table.setSelection(data);
            }
		}
	}

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

		if(isValueBlank(selection)) {
			Object data = Array.newInstance(clazz.getComponentType(), 0);
			table.setSelection(data);

		} else {
            if(table.isCellSelection()) {
				String[] cellInfos = selection.split(",");
				Cell[] cells = new Cell[cellInfos.length];

				for(int i = 0; i < cellInfos.length; i++) {
					cells[i] = buildCell(table, cellInfos[i]);
					table.setRowIndex(-1);	//clean
				}

				table.setSelection(cells);
			}
             else {
                String[] rowSelectValues = selection.split(",");
                Object data = Array.newInstance(clazz.getComponentType(), rowSelectValues.length);

                for(int i = 0; i < rowSelectValues.length; i++) {
                    table.setRowIndex(Integer.parseInt(rowSelectValues[i]));

                    Array.set(data, i, table.getRowData());
                }

                table.setSelection(data);
            }
		}
	}

    String resolveField(ValueExpression expression) {
        String expressionString = expression.getExpressionString();
        expressionString = expressionString.substring(2, expressionString.length() - 1);      //Remove #{}

        return expressionString.substring(expressionString.indexOf(".") + 1);                //Remove var
    }

    Cell buildCell(DataTable dataTable, String value) {
		String[] cellInfo = value.split("#");

		//Column
        int rowIndex = Integer.parseInt(cellInfo[0]);
		UIColumn column = dataTable.getColumns().get(Integer.parseInt(cellInfo[1]));

		//RowData
		dataTable.setRowIndex(rowIndex);
		Object rowData = dataTable.getRowData();

		//Cell value
		Object cellValue = null;
		UIComponent columnChild = column.getChildren().get(0);
		if(columnChild instanceof ValueHolder) {
			cellValue = ((ValueHolder) columnChild).getValue();
		}

		return new Cell(rowData, column.getId(), cellValue);
	}
}

O que muda eh o metodo decodeSortRequest
no trecho 

else {
            List sortData = new ArrayList();
            List list = (List) table.getValue();
            sortData.addAll(list);
            Collections.sort(sortData, new BeanPropertyComparator(sortColumn, table.getVar(), asc));
            table.setRowIndex(-1);      //cleanup
            table.setValue(sortData);

        }

soh isso.

postei essa solucao pois peskisei muito sobre ela e nao encontrei nada.

Espero que gostem.

2 Respostas

C

Olá elbesh

essa dica será muito útil, pois estou com este problema.
Não consegui entender sua solução. Basta criar este pacote e uma classe chamada DataHelper substituindo o código?

Você poderia me detalhar um poiuco mais a solução?

Agradeço

M

amigo, comigo funcionou normal...sem fazer nada disso.

nao sei se é porque o PrimeFaces foi atualizado, mas nao precisei fazer nada disso ai.

no meu caso utilizei LazyDataModel.

Segue o código

package dao;


import java.util.ArrayList;  

import java.util.Iterator;  
import java.util.List;  
import java.util.Map;    

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import model.Pessoa;


import org.primefaces.model.LazyDataModel;  
import org.primefaces.model.SortOrder;  


public class LazyPessoaDataModel extends LazyDataModel<Pessoa> {  
      
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private List<Pessoa> datasource;  
      
	public LazyPessoaDataModel(List<Pessoa> datasource) {  
        this.datasource = datasource;  
    } 
      
    @Override  
    public Pessoa getRowData(String rowKey) {  
    	
    	 Integer id = Integer.valueOf(rowKey);
    	 
        for(Pessoa pessoa : datasource) {  
        	 if(id.equals(pessoa.getCodigo())){
                return pessoa;  
        	 }
        }  
  
        return null;  
    }  
  
    @Override  
    public Object getRowKey(Pessoa pessoa) {  
        return pessoa.getCodigo();  
    }  
  
    
    @SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
    public List load(int first, int pageSize, String sortField, SortOrder sortOrder, Map filters) {
		    List data = new ArrayList();
		    
		    System.out.println("Executando Load()");
		    EntityManagerFactory emf = Persistence.createEntityManagerFactory("projetoSistema");
		    EntityManager em = emf.createEntityManager();
		
		    // CRITERIA
		    CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
		    CriteriaQuery accountQuery = criteriaBuilder.createQuery(Pessoa.class);
		
		    
		    // FROM
		    Root from = accountQuery.from(Pessoa.class);
		
		    
		    //SORT
		    if(sortField != null) {
			    if (sortOrder == SortOrder.ASCENDING) {
			    	accountQuery.orderBy(criteriaBuilder.asc(from.get(sortField)));
			    }
			    else {
			    	accountQuery.orderBy(criteriaBuilder.desc(from.get(sortField)));
			    }
		    }
		
		    // FILTROS
		    List predicates = new ArrayList();
		    for(Iterator it = filters.keySet().iterator(); it.hasNext();) {
				    String filterProperty = (String) it.next(); // table column name = field name
				    String filterValue = (String) filters.get(filterProperty);
				
				    Expression literal = criteriaBuilder.literal((String)filterValue);
				    predicates.add(criteriaBuilder.like(from.get(filterProperty), literal));
		    }
		    accountQuery.where((Predicate[]) predicates.toArray(new Predicate[predicates.size()]));
		
		    
		    
		    // PAGINATE
		    data = em.createQuery(accountQuery).setFirstResult(first).setMaxResults(getPageSize()).getResultList();
		
		    
		    
		    // ROW COUNT
		    CriteriaQuery countQuery = criteriaBuilder.createQuery(Long.class);
		    countQuery.select(criteriaBuilder.count(countQuery.from(Pessoa.class)));
		    countQuery.where((Predicate[]) predicates.toArray(new Predicate[predicates.size()]));
		   
		    
		    
		    int rowCount = Integer.parseInt(em.createQuery(countQuery).getSingleResult().toString());
		    setRowCount(rowCount);
		
		    return data;
    }

	 
 }
package bean;

import java.io.Serializable;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;

import org.primefaces.model.LazyDataModel;



import dao.LazyPessoaDataModel;
import dao.PessoaDAO;

import model.Pessoa;


@ManagedBean
@ViewScoped // SESSION OU VIEW SCOPED PARA CONSEGUIR ORDENAR
public class PessoaBean implements Serializable {

	private static final long serialVersionUID = 1L;
	
	
	private LazyDataModel<Pessoa> lazyModel;
    private Pessoa selectedPessoa;  
  
    private List<Pessoa> listaPessoas;  
    
    
   	private Pessoa pessoa = new Pessoa();
   	PessoaDAO pessoaDAO = new PessoaDAO();
   	
   	
    @PostConstruct 
    protected void init() {  
			
		System.out.println("Executando INIT()");
	      listaPessoas = pessoaDAO.exibirPessoas();
	      lazyModel = new LazyPessoaDataModel(listaPessoas); // DATA SOURCE
 	
    }  
	
	public LazyDataModel<Pessoa> getLazyModel() {  
    	System.out.println("Executando getLazyModel()");
    	
    	
         return lazyModel;  
    }  
    
	

   	public Pessoa getSelectedPessoa() {  
        return selectedPessoa;  
    }  
  
    public void setSelectedPessoa(Pessoa selectedPessoa) {  
        this.selectedPessoa = selectedPessoa;  
    }  
      
    
	



	public List<Pessoa> getListaPessoas(){
   		
			System.out.println("Retornou Consulta em Cache");
	        return listaPessoas;
   	}
   	

  
   

}
Criado 8 de janeiro de 2011
Ultima resposta 25 de out. de 2012
Respostas 2
Participantes 3