Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

Dúvida no Ex. 8 da Aula 6 - Páginas mais dinâmicas com AJAX

Olá.

Ainda estou finalizando os exercicios deste capitulo do curso de JSF, entretanto tenho uma dúvida particular sobre uma implementação, onde não sei se utilizo ou não o AJAX.

Estou implementando um controle de ponto, onde tenho um xhtml para cadastro de colaboradores e um outro que registra efetivamente o ponto (entrada, saida para almoco, retorno do almoco, saida). Até este ponto, não tenho dificuldades e consegui implementar. Preciso gerar um relatorio de ponto para cada colaborador. Pensei numa combobox para selecionar o colaborador e apos selecionado, um datatable mostraria todas as entradas na tabela de ponto para aquele colaborador.

A dúvida é qual a melhor forma de implementar. Como fazer para renderizar o datatable a partir de uma escolha feita no combobox (h:selectOneMenu)? Daria para implementar via AJAX?

5 respostas

Oi Angelo,

vc pode usar ajax sim. É o mesmo tag <f:ajax ../> que fica dentro do h:selectOneMenu. O <f:ajax> possui um atributo listener para associar um método e carregar os dados da tabela, ok?

abs

solução!

Oi Angelo,

só complementando, o <f:ajax .../> possui diversos atributos que você pode utilizar nesse sentido. Você pode definir o momento em que realizar a atualização da tabela com um event = "change", utilizar o render para identificar o datatable que se quer atualizar. você acaba tendo algo como:

<h:form id="form">
...
<h:selectOneMenu ... >
    <f:ajax event="change" execute="@this" render=":form:tabela" />
</h:selectOneMenu >
...
<h:dataTable id="tabela"... >
...
</h:dataTable 
....
</h:form>

Apenas um exemplo. Você pode chamar o método tanto dentro do h:selectOneMenu pelo valueChangeListener como dentro do f:ajax como já foi apresentado pelo colega acima. Tudo depende da sua necessidade e preferência.

Prezados, muito obrigado pelas respostas.Estou num impasse. Estou desenvolvendo um relatório de ponto eletrônico. Tenho um combo box onde seleciono o nome do funcionário e logo abaixo tenho um datatable que , a partir do seu id, retorna todas as horas lançadas para aquele funcionário na tabela de registros.O problema é que quando a tela é renderizada e o combo box é preenchido, mas o id do funcionário não é passado para o datatable e estou recebendo a seguinte exceção:

javax.el.ELException: /report.xhtml @22,70 value="#{registryBean.registriesById}": Error reading 'registriesById' on type br.com.angelo.beans.RegistryBean
Caused by: java.lang.IllegalArgumentException: org.hibernate.QueryException: could not resolve property: person_id of: br.com.angelo.model.Registry [select r from br.com.angelo.model.Registry r where r.person_id = :pId]

A minha suspeita é que quando a view é carregada, o combo box não retorna o id da opção "default" e por isso a pesquisa não pode ser feita, já que depende do id.

Abaixo, o xhtml:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!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:f="http://java.sun.com/jsf/core">



<h:body>
    <h:form>
        <fieldset>
            <legend> Ponto </legend>
            <h:panelGrid columns="2">
                <h:selectOneMenu value="#{registryBean.personId}">

                    <f:selectItems value="#{pb.persons}" var="person"
                        itemLabel="#{person.firstName}" itemValue="#{person.id}">
                    </f:selectItems>
                </h:selectOneMenu>
            </h:panelGrid>
        </fieldset>
        <h:dataTable value="#{registryBean.registriesById}" var="registry">
            <h:column>
                <h:outputLabel value="#{registry.timeInMillis}"/>
            </h:column>

        </h:dataTable>
    </h:form>



</h:body>
</html>

Abaixo, o código do bean:

package br.com.angelo.beans;

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

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import br.com.angelo.dao.PersonDAO;
import br.com.angelo.dao.RegistryDAO;
import br.com.angelo.model.Person;
import br.com.angelo.model.Registry;

@ManagedBean(name="registryBean")
@ViewScoped

public class RegistryBean implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private Registry registry = new Registry();
    private long timeInMillis;
    private Integer personId;


    public long getTimeInMillis() {
        return timeInMillis;
    }
    public void setTimeInMillis(long timeInMillis) {
        this.timeInMillis = timeInMillis;
    }    

    public Integer getPersonId() {
        return personId;
    }
    public void setPersonId(Integer personId) {
        this.personId = personId;
    }

    public Registry getRegistry() {
        return registry;
    }
    public void setRegistry(Registry registry) {
        this.registry = registry;
    }

    public List<Registry> getRegistriesById() {

        return new RegistryDAO().getRegistriesById(this.personId);

    }

    public String  gravar() {

        Person person = new PersonDAO().buscaPorCPF(cpf);
        RegistryDAO regDao = new RegistryDAO();
        registry.setTimeInMillis(Calendar.getInstance().getTimeInMillis());
        registry.setPerson(person);
        regDao.persistRegistry(registry);
        this.registry = new Registry();
        System.out.println(this.timeInMillis);
        return "success";

    }




}

E finalmente, o código do DAO:

package br.com.angelo.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import br.com.angelo.model.Person;
import br.com.angelo.model.Registry;

public class RegistryDAO {

    public void persistRegistry(Registry registry) {

        EntityManager em = new JPAUtil().getEntityManager();
        em.getTransaction().begin();
        em.persist(registry);
        em.getTransaction().commit();
        em.close();

    }

    public List<Registry> getRegistriesById(Integer id) {

        String queryString = "select r from Registry r where r.person_id = :pId";
        EntityManager em = new JPAUtil().getEntityManager();
        Query query = em.createQuery(queryString);
        query.setParameter("pId", id);
        @SuppressWarnings("unchecked")
        List<Registry> registries = query.getResultList();
        em.close();
        return registries;

    }

    public List<Registry> getRegistriesByCpf(String cpf) {

        EntityManager em = new JPAUtil().getEntityManager();
        Query query = em.createQuery("select p from Person p where p.cpf = :pCpf");
        query.setParameter("pCpf", cpf);
        Person person = (Person) query.getSingleResult();
        Query query2 = em.createQuery("select r from Registry r where r.person_id = :personId");
        query2.setParameter("personId", person.getId());
        @SuppressWarnings("unchecked")
        List<Registry> registries = query2.getResultList();

        em.close();


        return registries;
    }

}

O que vocês acham?  A minha suspeita faz sentido?

Mais uma vez obrigado.

Abraços.

Caro Angelo,

O problema é outro... Apesar de você não colocar a entidade, eu acredito que o problema é a chamada ao banco. Você está utilizando Hibernate. Nesse caso, o comando HQL seria:

select r from br.com.angelo.model.Registry r where r.personId = :pId

que aparece nos métodos getRegistriesById e getRegistriesByCpf do seu Dao. Você deve usar a variável que recebeu a anotação @Column e não o nome da coluna, a partir do momento que você chama o objeto (ou lista) utilizando a entidade como referência.

Abraço

Obrigado Narciso. Também cheguei a esta conclusão. O problema é que em HQL temos de pensar 'orientado a classes' e é justamente ai que eu estava errando.

Mas valeu demais pelo retorno.

Grande abraço.