Bom dia,
Alguém saberia me dizer se existe uma forma de se montar combos relacionados que não fosse "na unha" utilizando o JBoss Seam junto com o RichFaces ?
Eu fiz umas tentativas mas não deu mto certo…
o código ficou o seguinte…
ComboAjax.xhtml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
template="layout/template.xhtml">
<ui:define name="body">
<h:messages styleClass="message"/>
<h:form>
<!-- PAIS -->
<s:decorate id="SelecaoPais" template="layout/edit.xhtml">
<ui:define name="label">País</ui:define>
<h:selectOneMenu id="cb_pais"
value="#{comboPaisEstado.pais}" >
<s:selectItems value="#{paisList.resultList}"
var="pais"
label="#{pais.nome}"
noSelectionLabel="Selecione o país"/>
<s:convertEntity />
<a:support event="onchange"
action="#{comboPaisEstado.onChangePais}"
reRender="SelecaoPais" />
</h:selectOneMenu>
</s:decorate>
<!-- ESTADO -->
<s:decorate id="SelecaoEstado" template="layout/edit.xhtml">
<ui:define name="label">Estado</ui:define>
<h:selectOneMenu id="cb_estado"
value="#{comboPaisEstado.estado}" >
<s:selectItems value="#{comboPaisEstado.pais.estados}"
var="estado"
label="#{estado.nome}"
noSelectionLabel="Selecione o estado"/>
<s:convertEntity />
</h:selectOneMenu>
</s:decorate>
</h:form>
</ui:define>
</ui:composition>
Componente que trabalha o onChange
package session.beans;
import entity.beans.Estado;
import entity.beans.Pais;
import helper.JPAHelper;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.jboss.seam.annotations.Name;
@Name("comboPaisEstado")
public class ComboPaisEstado {
/** Creates a new instance of ComboPaisEstado */
public ComboPaisEstado() {
}
/* adicionado */
private Pais pais = new Pais();
private Estado estado = null;
public Pais getPais() {
return pais;
}
public void setPais(Pais pais) {
this.pais = pais;
}
public Estado getEstado() {
return estado;
}
public void setEstado(Estado estado) {
this.estado = estado;
}
public void onChangePais(){
JPAHelper.initEMF();
EntityManager em = JPAHelper.getEntityManager();
Query query = em.createQuery( "select estado from Estado estado where estado.pais.id = :idPais" );
query.setParameter( "idPais", pais.getId() );
Set<Estado> estados = new HashSet<Estado>();
estados.addAll( (List<Estado>) query.getResultList() );
pais.setEstados( estados );
}
}
Pelo site de exemplos do RichFaces não existe nda parecido, assim como na documentação do Seam…
Não queria ter o mesmo trabalho pra fazer isso como nos tempos de Struts 1.2.X onde tinha que montar as funções JS de requisição e de callback…
Se puderem me indicar uma maneira mais tranquila de se fazer isso eu agradeço !
Boa Tarde pessoal,
como consegui resolver o problema passei aqui para deixar a solução, pode ser que seja útil para alguém mais pra frente…
A solução é bem simples, na tag a:support colocada dentro do primeiro combo definimos que no evento onchange o componente de id cb_estado terá de ser renderizado novamente. E como o selectItems do segundo combo é uma coleção que está contida dentro do objeto da primeira seleção, o mesmo é populado quendo selecionamos o primeiro objeto…
Tah ai o código:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich" template="layout/template.xhtml">
<ui:define name="body">
<h:messages styleClass="message" />
<h:form>
<!-- PAIS -->
<h:selectOneMenu id="cb_pais" value="#{comboPaisEstado.pais}">
<s:selectItems value="#{paisList.resultList}"
var="pais"
label="#{pais.nome}"
noSelectionLabel="Selecione o país" />
<s:convertEntity />
<a:support event="onchange" [b]reRender="cb_estado"[/b] ignoreDupResponses="true" />
</h:selectOneMenu>
<!-- ESTADO -->
<h:selectOneMenu [b]id="cb_estado"[/b] value="#{comboPaisEstado.estado}">
<s:selectItems [b]value="#{comboPaisEstado.pais.estados}"[/b]
var="estado"
label="#{estado.nome}"
noSelectionLabel="Selecione o estado" />
<s:convertEntity />
</h:selectOneMenu>
<a:status>
<f:facet name="start">
<h:graphicImage value="/img/loading.gif"/>
</f:facet>
</a:status>
</h:form>
</ui:define>
</ui:composition>
Eu criei uma solução para isso utilizado o auto completar do rich faces e um conversor personalizado do JSF. Para não sobrecarregar o servidor com consustas sql criei uma Factory do Seam para essas entidades.
Se alguem quiser dar uma olhada: http://www.chutaqueemacumba.com.br/ChutaQueEMacumba/site/cadastre.seam
Só digitar o nome da sua cidade que será autocompletado.
Se agradar alguem posso compartilhar.
Att.
Cara vcs podem mandar o código para essa solução? Estou passando por um probleminha… abraços
Devido a varias pessoas que tem me pedido vou preparar um tutorial junto aos fontes que desenvolvi e postarei aqui ok!
Abraços
e ae cara, pode ser uma boa, mas pode mandar esse pedacinho do código só para eu tentar… vou postar aqui meu código…
ainda esotu tentando ajeitar, não é o código final, algumas váriaveis vão sair…
package com.citespace.bean.list;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.faces.convert.Converter;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import com.citespace.bean.list.interfaces.ICountryList;
import com.citespace.cms.model.Country;
import com.citespace.converter.CountryConverter;
@Stateful
@Name("countryList")
@Scope(ScopeType.EVENT)
public class CountryList implements ICountryList, Serializable{
/**
*
*/
private static final long serialVersionUID = 4824589054075219364L;
private List<Country> mCountry;
private Map<String, Country> mCountryMap;
private Country country = null;
@PersistenceContext(unitName="citespace-jpa")
private EntityManager em;
@Create
@SuppressWarnings("unchecked")
public void loadCountry(){
mCountry =
em.createQuery("select c from Country c ").getResultList();
Map<String, Country> results = new TreeMap<String, Country>();
for(Country c:mCountry){
results.put(c.getName(), c);
}
mCountryMap = results;
}
public Map<String, Country> getAllCountries(){
return mCountryMap;
}
public Converter getConverter(){
return new CountryConverter(mCountry);
}
@Remove @Destroy
public void destroy(){}
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
}
package com.citespace.bean.list;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.faces.convert.Converter;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import com.citespace.bean.list.interfaces.IStateList;
import com.citespace.cms.model.Country;
import com.citespace.cms.model.State;
import com.citespace.converter.StateConverter;
@Stateful
@Name("stateList")
@Scope(ScopeType.EVENT)
public class StateList implements IStateList, Serializable{
/**
*
*/
private static final long serialVersionUID = -1901355293311882031L;
private List<State> mState;
private Map<String, State> mStateMap;
private Country country = null;
private State state = null;
@PersistenceContext(unitName="citespace-jpa")
private EntityManager em;
@Create
@SuppressWarnings("unchecked")
public void loadState(){
Query q =
em.createQuery("select s from State s ");
mState = q.getResultList();
Map<String, State> results = new TreeMap<String, State>();
for(State s:mState){
results.put(s.getName(), s);
}
mStateMap = results;
}
public Map<String, State> getAllStates(){
return mStateMap;
}
@SuppressWarnings("unchecked")
public Map<String, State> getStatesByCountry(){
Query q = em.createQuery("select s from State s Join s.country c Where c.id = :countryId");
q.setParameter("countryId", country.getId());
mState = q.getResultList();
Map<String, State> results = new TreeMap<String, State>();
for(State s:mState){
results.put(s.getName(), s);
}
return mStateMap;
}
public Converter getConverter(){
return new StateConverter(mState);
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
@Remove @Destroy
public void destroy(){}
}
<h:outputLabel value="Country * :" for="c" />
<h:selectOneMenu value="#{stateList.country}" converter="#{countryList.converter}" required="true" id="srchCountry" >
<s:selectItems noSelectionLabel="-- Select a country --" />
<s:selectItems value="#{countryList.allCountries}" id="c" var="country" label="#{country.value}"/>
<a4j:support event="onchange" reRender="s" ignoreDupResponses="true" />
</h:selectOneMenu>
<h:outputLabel value="State * :" for="s" />
<h:selectOneMenu value="#{stateList.state}" converter="#{stateList.converter}" required="true" id="srchState" >
<s:selectItems noSelectionLabel="-- Select a state --" />
<s:selectItems value="#{stateList.statesByCountry}" id="s" var="state" label="#{state.value}" />
</h:selectOneMenu>
só que não consigo funcionar o ajax para trazer de um determinado país… pode me dar uma dica, please?
to pegando esse erro
14:09:16,391 ERROR [viewhandler] Error Rendering View[/page/users.xhtml]
javax.faces.FacesException: javax.el.ELException: /page/users.xhtml @48,106 value="#{stateList.statesByCountry}": Error reading 'statesByCountry' on type org.javassist.tmp.java.lang.Object_$$_javassist_seam_3
at javax.faces.component.UISelectItems.getValue(UISelectItems.java:144)
at org.jboss.seam.ui.component.UISelectItems.getValue(UISelectItems.java:161)
at com.sun.faces.renderkit.RenderKitUtils.getSelectItems(RenderKitUtils.java:289)
at com.sun.faces.renderkit.html_basic.MenuRenderer.renderSelect(MenuRenderer.java:814)
at com.sun.faces.renderkit.html_basic.MenuRenderer.encodeEnd(MenuRenderer.java:280)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:861)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:242)
at com.sun.faces.renderkit.html_basic.GridRenderer.renderRow(GridRenderer.java:180)
at com.sun.faces.renderkit.html_basic.GridRenderer.encodeChildren(GridRenderer.java:127)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
at org.jboss.seam.ui.util.cdk.RendererBase.renderChild(RendererBase.java:186)
at org.jboss.seam.ui.util.cdk.RendererBase.renderChildren(RendererBase.java:166)
at org.jboss.seam.ui.renderkit.ValidateAllRendererBase.doEncodeChildren(ValidateAllRendererBase.java:33)
at org.jboss.seam.ui.util.cdk.RendererBase.encodeChildren(RendererBase.java:92)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
at org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:282)
at org.ajax4jsf.renderkit.RendererBase.renderChildren(RendererBase.java:262)
at org.richfaces.renderkit.html.PanelRenderer.doEncodeChildren(PanelRenderer.java:220)
at org.richfaces.renderkit.html.PanelRenderer.doEncodeChildren(PanelRenderer.java:215)
at org.ajax4jsf.renderkit.RendererBase.encodeChildren(RendererBase.java:121)