Componentes JSF

1 resposta
L

Galera, venho recorrer a vós novamente,
estou com a seguinte dificuldade:
A ideia:
Criar um componente para paginação, que receberia basicamente 3 parãmetros, o total da pesquisa (o count() do db), um atributo que receberia a pagina atual. e um método a ser executado ao trocar de página.

O problema:
Ainda não encontrei uma forma de alterar o atributo no bean que use o componente.

Evolui a ideia e melhorando-á acredito que os 3 parâmetros não seriam suficientes, o mais eficiente é receber o start e o offset da pesquisa ex:

estou na pagina 1 então start = 0 e o offset = 10;
estou na pagina 3 então start seria 20 e o offset 30;

bom vamos aos códigos:

componente
<?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:cc="http://java.sun.com/jsf/composite"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:c="http://java.sun.com/jsp/jstl/core"
      xmlns:pou="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core">

    <!-- INTERFACE -->
    <cc:interface componentType="pagination">
        <cc:attribute name="total" required="true" type="java.lang.Integer" />
        <cc:attribute name="start" required="true"  type="java.lang.Integer" />
        <cc:attribute name="offset" required="true"  type="java.lang.Integer" />
        <cc:attribute name="numvisiblesitems" type="java.lang.Integer" />
        <cc:attribute name="styleClass" default="" />
        <cc:attribute name="numvisiblespages" default="5" type="java.lang.Integer" />
        <cc:attribute name="style" default="" />
        <cc:attribute name="update" default="@form" />
        <cc:attribute name="process" default="@form" />
        <!--renderiza acima do result table -->
        <cc:attribute name="renderTop" default="true" />
        
        <!--renderiza abaixo do result table -->
        <cc:attribute name="renderBottom" default="false" />
        <cc:attribute name="action" required="true"
                      method-signature="void action()" />
    </cc:interface>

    <!-- IMPLEMENTATION -->
    <cc:implementation>
        <!-- chama o bean do componente para os devidos cálculos -->
        #{cc.calculate()}
        <c:set var="numpages" value="#{cc.getPages()}" />
        <h:outputStylesheet library="css" value="components.css" name="components.css"/>
        
        <h:panelGroup layout="block" id="i#{cc.attrs.id}" 
                      class="pagination #{cc.attrs.styleClass}"
                      style="#{cc.attrs.style}"
                      rendered="#{cc.attrs.renderTop}">
            <ul>
                <ui:repeat value="#{cc.listPages}" var="p" >
                    <li>
                        <h:commandButton 
                            value="#{p.toString()}" >
                            <pou:ajax 
                            listener="#{cc.setNewPage(p)}"
                            update="#{cc.attrs.update}"
                            process="#{cc.attrs.process}"  />
                        </h:commandButton>
                    </li>
                </ui:repeat>
                <span><h:outputText value="Número de páginas:#{numpages}"></h:outputText></span>
            </ul>
        </h:panelGroup>
        <cc:insertChildren />

    </cc:implementation>

</html>
e o bean do componente
@FacesComponent("pagination")
public class Pagination extends UINamingContainer {

    private Integer total;
    private Integer numvisiblesitems;
    private Integer pages;
    private Integer firstPage;
    private Integer lastPage;
    private Integer start;
    private Integer end;
    private Integer actual = 1;
    private Integer numvisiblespages;
    private List<Integer> listPages;

    /**
     * chamado no pagination.xhtml para execução dos cálculos.
     */
    public void calculate() {

        numvisiblesitems = (Integer) this.getAttributes().get("numvisiblesitems");
        total = (Integer) this.getAttributes().get("total");
        numvisiblespages = (Integer) this.getAttributes().get("numvisiblespages");

        //trata o default para o número de items visualizáveis
        if (numvisiblesitems == null) {
            numvisiblesitems = 10;
        }

        if (total == null) {
            throw new IllegalArgumentException("Number of total must be defined!");
        }

        pages = (total / numvisiblesitems);

        if (pages * numvisiblesitems < total) {
            pages++;
        }

        updatePages();
    }

    private void updatePages() {
        updatePages(true);
    }

    private void updatePages(boolean starting) {

        //se for a primeira chamada a pagina é 1
        actual = starting ? 1 : actual;

        //inicio da paginação
        start = (actual * numvisiblesitems) - numvisiblesitems;

        if (start < 0) {
            start = 0;
        }

        //final da paginação
        end = start + numvisiblesitems;

        if (end > total) {
            end = total;
        }
        
        if (actual > numvisiblespages / 2) {
            firstPage = actual - numvisiblespages / 2;
        } else if (actual < numvisiblespages / 2) {
            firstPage = 1;
        } else {
            firstPage = actual - numvisiblespages / 2;
        }

        lastPage = firstPage + numvisiblespages;
        if (actual == total) {
            lastPage = total;
        }

        listPages = new ArrayList<Integer>();

        for (int i = firstPage; i <= lastPage; i++) {
            listPages.add(i);
        }

    }

    public void setNewPage(Integer p) {
        actual = p;
        updatePages(false);
    }

    //getter and setters

}

uma das dúvidas é, setar o atributo do bean que use este componente, a outra é, na tentativa de alterar a págima alguns cálculos devem ser realizados novamente, porém, aparentemente sem nenhuma exceção não consigo executar um método na class Pagination, na verdade apenas , um o que inicia a classe, o calculate(), os outros não são executados a partir do click do h:commandButton, há alguma coisa de errada no código? passei a usar o h:commandButton, pois com o p:commandButton, porém tanto um quanto o outro sem sucesso.

Qualquer ajuda é bem vinda.

1 Resposta

L

Encontrei o problema, basicamente estava tentando executar uma ação em um bean que não tem escopo, então alterei o componente , em vez de ele ter um Tipo, ele recebe como parâmetro o Pagination, assim ele calcula ao construir o componente, e o resto é alterado de acordo com a navegação, para utilizar basta o bean ter um atributo instanciado do Paginatio, e implementar o PaginationListener, que tem apenas um método, semelhante ao Runnable,
bom vou deixar as classes aqui, caso alguem queira utilizar.

public interface PaginationListener {
    void doAction();
}
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
@FacesComponent("pagination")
public class Pagination implements Serializable{

    private Integer total;
    private Integer numvisiblesitems;
    private Integer pages;
    private Integer firstPage;
    private Integer lastPage;
    private Integer start;
    private Integer end;
    private Integer current = 1;
    private Integer numvisiblespages;
    private List<Integer> listPages;
    private PaginationListener listener;

    public Pagination(Integer total, Integer numvisiblesitems, 
            Integer numvisiblespages, PaginationListener listener) {
        this.total = total;
        this.numvisiblesitems = numvisiblesitems;
        this.numvisiblespages = numvisiblespages;
        this.listener = listener;
        calculate();
    }

    
    public Pagination(Integer total,PaginationListener listener) {
        this.total = total;
        this.numvisiblesitems = 10;
        this.numvisiblespages = 5;
        this.listener = listener;
        calculate();
    }
    /**
     * chamado no pagination.xhtml para execução dos cálculos.
     */
    private void calculate() {

        //trata o default para o número de items visualizáveis
        if (numvisiblesitems == null) {
            numvisiblesitems = 10;
        }
        if(numvisiblespages == null){
            numvisiblespages = 5;
        }
        

        if (total == null) {
            throw new IllegalArgumentException("Number of total must be defined!");
        }

        pages = (total / numvisiblesitems);

        if (pages * numvisiblesitems < total) {
            pages++;
        }

        updatePages();
    }

    private void updatePages() {
        updatePages(true);
    }

    private void updatePages(boolean starting) {

        //se for a primeira chamada a pagina é 1
        current = starting ? 1 : current;

        //inicio da paginação
        start = (current * numvisiblesitems) - numvisiblesitems;

        if (start < 0) {
            start = 0;
        }

        //final da paginação
        end = start + numvisiblesitems;

        if (end > total) {
            end = total;
        }
        
        if (current > numvisiblespages / 2) {
            firstPage = current - numvisiblespages / 2;
        } else if (current < numvisiblespages / 2) {
            firstPage = 1;
        } else {
            firstPage = current - numvisiblespages / 2;
        }

        lastPage = firstPage + numvisiblespages;
        if (lastPage > pages) {
            lastPage = pages;
            firstPage = lastPage - numvisiblespages;
        }
        if(firstPage < 1){
            firstPage = 1;
        }

        listPages = new ArrayList<Integer>();

        for (int i = firstPage; i <= lastPage; i++) {
            listPages.add(i);
        }
        
        if(!starting){
            listener.doAction();
        }
    }

    public void setNewPage(Integer p) {
        current = p;
        updatePages(false);
        
    }

    public Integer getEnd() {
        return end;
    }

    public void setEnd(Integer end) {
        this.end = end;
    }

    public Integer getNumvisiblesitems() {
        return numvisiblesitems;
    }

    public void setNumvisiblesitems(Integer numvisiblesitems) {
        this.numvisiblesitems = numvisiblesitems;
    }

    public Integer getPages() {
        return pages;
    }

    public void setPages(Integer pages) {
        this.pages = pages;
    }

    public Integer getStart() {
        return start;
    }

    public void setStart(Integer start) {
        this.start = start;
    }

    public Integer getTotal() {
        return total;
    }

    public void setTotal(Integer total) {
        this.total = total;
    }

    public Integer getFirstPage() {
        return firstPage;
    }

    public void setFirstPage(Integer firstPage) {
        this.firstPage = firstPage;
    }

    public Integer getLastPage() {
        return lastPage;
    }

    public void setLastPage(Integer lastPage) {
        this.lastPage = lastPage;
    }

    public Integer getNumVisiblesPages() {
        return numvisiblespages;
    }

    public void setNumVisiblesPages(Integer numVisiblesPages) {
        this.numvisiblespages = numVisiblesPages;
    }

    public List<Integer> getListPages() {
        return listPages;
    }

    public void setListPages(List<Integer> listPages) {
        this.listPages = listPages;
    }

    public Integer getCurrent() {
        return current;
    }

    public void setCurrent(Integer current) {
        this.current = current;
    }
}
<?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:cc="http://java.sun.com/jsf/composite"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:c="http://java.sun.com/jsp/jstl/core"
      xmlns:pou="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core">

    <!-- INTERFACE -->
    <cc:interface>
        <cc:attribute name="styleClass" default="" />
        <cc:attribute name="style" default="" />
        <cc:attribute name="update" default="@form" />
        <cc:attribute name="process" default="@form" />
        <!--renderiza acima do result table -->
        <cc:attribute name="renderTop" default="true" />

        <!--renderiza abaixo do result table -->
        <cc:attribute name="renderBottom" default="false" />
        <cc:attribute name="pagination" required="true"
                      type="com.busker.web.components.Pagination" />
        <cc:attribute name="action" required="true"
                      method-signature="void action()" />
    </cc:interface>

    <!-- IMPLEMENTATION -->
    <cc:implementation>
        <!--call to componentType to calculate vars-->
        <c:set var="numpages" value="#{cc.attrs.pagination.setAction(cc.attrs.action)}" />
        <c:set var="numpages" value="#{cc.attrs.pagination.getPages()}" />
        <h:outputStylesheet library="css" value="components.css" name="components.css"/>
        <h:panelGroup layout="block" id="#{cc.attrs.id}t" 
                      class="pagination #{cc.attrs.styleClass}"
                      style="#{cc.attrs.style}"
                      rendered="#{cc.attrs.renderTop}">
            <ul>
                <ui:repeat value="#{cc.attrs.pagination.listPages}" var="p" >
                    <li class="#{cc.attrs.pagination.current == p?'selected':''}" >
                        <pou:commandButton  
                            value="#{p.toString()}"
                            action="#{cc.attrs.pagination.setNewPage(p)}"
                            update="#{cc.attrs.update}"
                            process="#{cc.attrs.process}"
                            />
                    </li>
                </ui:repeat>
                <span><h:outputText value="Número de páginas:#{numpages}"></h:outputText></span>
            </ul>
        </h:panelGroup>
        <cc:insertChildren />
        <h:panelGroup layout="block" id="#{cc.attrs.id}b" 
                      class="pagination #{cc.attrs.styleClass}"
                      style="#{cc.attrs.style}"
                      rendered="#{cc.attrs.renderBottom}">
            <ul>
                <ui:repeat value="#{cc.attrs.pagination.listPages}" var="p" >
                    <li class="#{cc.attrs.pagination.current == p?'selected':''}" >
                        <pou:commandButton  
                            value="#{p.toString()}"
                            action="#{cc.attrs.pagination.setNewPage(p)}"
                            update="#{cc.attrs.update}"
                            process="#{cc.attrs.process}"
                            />
                    </li>
                </ui:repeat>
                <span><h:outputText value="Número de páginas:#{numpages}"></h:outputText></span>
            </ul>
        </h:panelGroup>
    </cc:implementation>

</html>

Abraços.

Criado 9 de junho de 2012
Ultima resposta 10 de jun. de 2012
Respostas 1
Participantes 1