Ajax en JSF 2.0 - Ejemplo 2: Tabla actualizada según se escriba
Siguiendo con los ejemplos después de mucho tiempo, ahora mostraré cómo actualizar una lista dependiendo del texto que se escribe en un input-text, pero usando Ajax. Es decir, a medida que se escribe, se actualizará el contenido del texto. Todo esto usando JSF 2.0 con su tag
El contenido será mostrado en un
Ahora, la parte más esperada: el input-text con el Ajax.
Realmente consiste en un tag h:inputText que tiene dentro un tag f:ajax. El que hace realmente el trabajo es este último tag.
Y listo, lo ejecutamos y ya.
Este proyecto, como todos los demás, debería ejecutarse si problemas en un NetBeans IDE 6.8/6.9, usando GlassFish v3. Aquí está para descargarlo.
<ajax />
El EJB
Para comenzar, debemos tener un lista de elementos que se actualizarán de acuerdo a un parámetro. Yo tengo un EJB que hace una consulta por JPA-API a mi base de datos "samples" (Esta base de datos viene como parte de las bases de datos de ejemplo de Java DB / Apache Derby y que son accesibles desde NetBeans). La entidad que estoy manejando es elManufacturer
.public List<Manufacturer> findByName(String name) { String $name = "%" + name.replaceAll(" ", "%") + "%"; CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); CriteriaQuery<Manufacturer> criteriaQuery = criteriaBuilder.createQuery(Manufacturer.class); Root<Manufacturer> manufacturer = criteriaQuery.from(Manufacturer.class); criteriaQuery.select(manufacturer); criteriaQuery.where(criteriaBuilder.like(manufacturer.get("name").as(String.class), $name)); List<Manufacturer> list = em.createQuery(criteriaQuery).getResultList(); return list; }
El ManagedBean
Ahora, el ManagedBean que se comunicará con la interfaz de usuario y le dirá qué mostrar. Este tiene un atributo llamado"nombre"
que estará asociado al input-text del formulario que el usuario verá. Lo que escriba se guardará ahí, y será tomado para la búsqueda en la base de datos.@ManagedBean(name = "formBean") @SessionScopedpublic class ManufacturerManagedBean { static final Logger LOGGER = Logger.getLogger(ManufacturerManagedBean.class.getName()); @EJB private ManufacturerFacade manufacturerFacade; //el EJB private String nombre = ""; //el atributo que estará asociado al input-text private List<Manufacturer> manufacturerList; //la lista a mostrar /** Creates a new instance of ManufacturerManagedBean */ public ManufacturerManagedBean() { } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public List<Manufacturer> getListByName() { if (manufacturerList == null) { //si es la primera vez que se accederá a la lista... manufacturerList = manufacturerFacade.findByName(nombre); //... actualizar el contenido } return manufacturerList; //devuelve la lista con los elementos encontrados } public void nombreChangeListener(AjaxBehaviorEvent event) { //cada vez que haya un cambio en el texto, vuelve a generar la lista manufacturerList = manufacturerFacade.findByName(nombre); } }
El .xhtml
Y, en la tercera capa, vemos el .xhtml que mostrará el contenido actualizado y el formulario.El contenido será mostrado en un
<h:dataTable />
como cualquier resultado. Tendrá como ID=manufacturerTable
. Este ID es importante porque es por donde el Ajax le dirá qué elemento de la página debe actualizar.<h:dataTable value="#{formBean.listByName}" border="1" var="item" id="manufacturerTable"> <h:column> <f:facet name="header"> ID </f:facet> <h:outputText value="#{item.manufacturerId}" /> </h:column> <h:column> <f:facet name="header"> Nombre </f:facet> <h:outputText value="#{item.name}" /> </h:column> <h:column> <f:facet name="header"> e-mail </f:facet> <h:outputText value="#{item.email}" /> </h:column> </h:dataTable>
Ahora, la parte más esperada: el input-text con el Ajax.
Realmente consiste en un tag h:inputText que tiene dentro un tag f:ajax. El que hace realmente el trabajo es este último tag.
<h:inputText id="nombreFiltro" autocomplete="off" value="#{formBean.nombre}" > <f:ajax render="manufacturerTable" event="keyup" listener="#{formBean.nombreChangeListener}"/> </h:inputText>
- El atributo
render
dice qué IDs del HTML se van a actualizar. Aquí dice que es el ID del dataTable. - El atributo
event
dice qué evento del tag inputText (porque está manejando los eventos del tag que lo envuelve) va ejecutar el ajax. En este caso será el evento keyup del input-text. - El atributo
listener
indica cuál es el método que se ejecutará cuando suceda el evento. En este caso es el métodonombreChangeListener
del ManagedBean que hemos creado hace un momento.
Y listo, lo ejecutamos y ya.
El proyecto
Este proyecto, como todos los demás, debería ejecutarse si problemas en un NetBeans IDE 6.8/6.9, usando GlassFish v3. Aquí está para descargarlo.
excelente Diego
ResponderBorrarMuy buen articulo Diego.
ResponderBorrarQuiero hacer un pequeño aporte a indicando que es posible actualizar una lista de campos, por medio del argumento render algo como esto:
f:ajax render="manufacturerTable campo1 campo2 ..." ...
Util por ejemplo cuando tenemos un formulario que deseamos refrescar segun el Id digitado por el usuario
HOLA, OYE LAVERDAD ES QUE ME HAN GUSTADO TUS ARTICULOS Y ME PARECEN MUY BUENOS, YO TRABAJE CON FACES 1.2 Y CON EL FACES CONFIG, PERO AHORA QUE ME HE MUDADO A FACES 2.0 NO PUEDO HACER QUE FUNCIONE LAS ANOTACIONES, ES DECIR QUE HAGO EL BEAN Y TRATO DE INTERACTUAR CON EL Y NO FUNCIONA ME DICE QUE LA ETIQUETA DEL MB DECLARADA EN LA ANOTACION NO EXISTE QUE NO ENCUENTRA EL BEAN, ME PODRIAS AYUDAR????
ResponderBorrarHola
ResponderBorrarte has asegurado que está ejecutándose en un servidor JavaEE 6 ? Porque esta anotación es nueva en esta versión.
Hola, te comento que no se puede acceder al archivo que publicaste.
ResponderBorrarListo, gracias anónimo :)
ResponderBorrarresulta que el sitio java.net está migrando de plataforma. Ya actualicé el enlace. Seguiré revisando los demás post.
gracias nuevamente
Muy bueno Diego, una pregunta, ¿como podría hacer esto mismo solo que sin utilizar EJB y solo utilizando clases Java y ManagedBeans con una BD en MySQL? estoy empezando a ver JSF 2.0 y me gustaría algo como esto... Gracias y buen ejemplo
ResponderBorrarHola buen ejemplo, me gustaría que me explicaras que diferencias tiene un SessionScopedpublic de un SessionScoped
ResponderBorrarSaludos
Hola excelente articulo me funciono correctisimo. Tengo una situacion, en mi bd tengo los registros mezclados con letras minusculas y/o mayusculas, pero al escribir en el inputText si lo escribo todo minuscula por ejemplo y en la bd se encuentra con letra inicial mayuscula obviamente no coincide y no me lo devuelvo como puedo hacer para que digamos el valor que viene de la bd me lo pase a minuscula para que todo lo que escriba me lo pase tambien a minuscula y de esa manera supongo hara una comparacion de caracteres todo en minusculas, espero me haya dado a comprender.
ResponderBorrarPuedes echarme una mano y como poder resolver esta situacion
De antemano muchas gracias
Hola Manfredo
Borrarestas usando JPA como en este ejemplo? si es así, intenta con cambiar la línea 7 del primer código de este ejemplo (o en el mismo código fuente, en la línea 33 de la clase ManufacturedFacade.java) con lo siguiente:
criteriaQuery.where(criteriaBuilder.like( criteriaBuilder.upper( manufacturer.get("name").as(String.class)), $name.toUpperCase()));
Si te das cuenta, se trata de hacerlo uniforme: todo en mayúsculas tanto el campo de la tabla (criteriaBuilder.upper()) como el argumento ($name.toUpperCase()).