Atualizar valor quando fecha ModalPanel [RESOLVIDO]

15 respostas
F

Boa tarde galera,

Eu tenho um commandLInk que abre um <rich:modalPanel para eu fazer pesquisa. Ate ai tudo bem. So que eu queria fazer o seguinte. Quando eu fechar o modal, a tela que chamou o modal atualiza para que eu possa pegar o valor que foi pesquisado no modal. Esse valor que foi pesquisado nao corre o risco de perde-lo pq ele esta na sessao. Alguem tem uma ideia de como fazer isso?
Eu nao posso fazer dependencia de telas pq a tela de pesquisa é utilizada em outros lugares no sistema.

Se alguem puder ajudar eu agradeço. Ja tem um tempinho que estou com esse problema e preciso resolver.

Muito obrigado galera.

15 Respostas

F

alguem tem uma ideia gente?
obrigado.

P

Opa! Agora que vi sua mensagem. Vamos lá… Estava pensando aqui, pq vc não implementa o padrão observer para fazer isso? Tipo assim, vc abre o Modal (passando o Managed Bean, que será o observador, como parâmetro), realiza a pesquisa, alimenta o valor resultante na sessão e notifica o observador(Managed Bean) que faz o que tem que fazer com o valor. Daí no oncomplete do commandLink vc colocar um reRender para atualizar o valor na tela. Não fiz aqui não mas, acho que funciona. Valeu!

Paz e bem!

F

Opa Paulo. Muito obrigado pela resposta cara… Li o exemplo que você passou, é meio complicado né, mas vou tentar implementar a ideia. rs.

vlw… Assim q consegui posto alguma coisa.

P

Né nada cara, o monstro não é tão bravo assim. :slight_smile: Veja se este exemplo te ajuda a entender.

Paz e bem!

F

Eu li o exemplo que você postou, e encontrei outros na net tb para aprender mais sobre o assunto.
Olha so o problema. Você disse para eu colocar no oncomplete do commandLink um reRender para ele buscar as atualizaçoes que estao na sessao. O codigo que abre o modal é o seguinte.

<a4j:commandLink id="btnPesq" title="Pesquisar"
   //abre o modal de pesquisa
   oncomplete="Richfaces.showModalPanel('panel')" reRender="panel"
   //Esse action aki chama o metodo para destroir se o bean estiver na sessao para o modal nao abrir ja populado.
   action="#{pesquisaDepartment.destroy}">
   <h:graphicImage id="image1" url="/images/search.gif"
   style="border:0; height: 17px;" />
   //tentei colocar esse support aki mas nao serviiu de nada.
   <a4j:support event="oncomplete" reRender="txtDp"/>							
</a4j:commandLink>

A ideia de buscar na sessao o valor que foi pesquisado foi boa. Porém nao acho lugar para fazer isso nesse codigo. Você tem alguma?

P

Faz o seguinte, esquece o oncomplete. Escrevi bobeira…

Na página que chama o modal panel vc faz +/- assim…

&lt;ui:include src="/panel.xhtml"&gt;
    // Aqui vc está passando o Managed Bean para o Modal Panel
    &lt;ui:param name="bean" value="#{pesquisaDepartment}" /&gt;
&lt;/ui:include&gt;
.
.
.
&lt;h:inputText id="txtDp" value="#{pesquisaDepartment.departamento.nome}"/&gt;
&lt;a4j:commandLink id="btnPesq" title="Pesquisar" onclick="Richfaces.showModalPanel('panel')" reRender="txtDp" /&gt;

No arquivo do modal panel (panel.xhtml ou .jspx) vc coloca +/- isso:

...
&lt;rich:modalPanel id="panel" showWhenRendered="false"&gt;
&lt;a4j:form id="formPanel"&gt;
	...
	// Daí se for um dataTable, para cada linha resultante vc pode fazer isso
	&lt;rich:dataTable id="tabelaDpto" value="#{beanDePesquisaDeDepartamentos.departamentos}" var="departamento"&gt;
		&lt;rich:colunm id="nome"&gt;
			&lt;a4j:commandLink value="#{departamento.nome}" onclick="Richfaces.hideModalPanel('panel')" &gt;
				&lt;f:setPropertyActionListener target="#{beanObserver.departamento}" value="#{departamento}" /&gt;
			&lt;/a4j:commandLink&gt; 
		&lt;/rich:colunm&gt;
	&lt;/rich:dataTable&gt;
	// Observe que todos o Managed Beans que vc passar como parâmetro devem ter a propriedade departamento (devem implementar a mesma interface)
	...
&lt;/a4j:form&gt;
&lt;/rich:modalPanel&gt;
...

Daí ele seta o departamento no beanObserver e reRender=“txtDp” atualiza para o departamento escolhido. Com isso vc nem vai precisar de guardar o valor na sessão. Vê se funciona…

Paz e bem!

F

Boa tarde Paulo… Caaara… Essa parada eh muito loka… hj eu nao to ralando, entao aproveitei o dia para estudar e pegar uns exemplos dessa parada. peguei um exemplo mais concreto num tutorial do GUJ http://www.guj.com.br/article.show.logic?id=47 e vi como a coisa funciona. Segunda feira eu vou tentar fazer la no trampo. Assim que consegui eu te falo.

vlw cara pela ajuda.

F

Bom dia Paulo…
Olha soh, quando eu dou o <ui:include eu passo o bean da tela observadora para o bean da tela que esta sendo observada, certo? Poise, a tag <ui:param nao consegue passar o bean como você mencionou no topico acima. no bean observado, eu criei o construtor que recebe um Observador e nao criei o construtor padrao(sem parametros). Ele da um erro falando que nao consegue instanciar o bean observado. Se eu criar o construtor padrao, ele entra normal pelo construtor padrao, e nao pelo construtor que recebe um observador. Veja como ta meu codigo para ver se consegue me ajudar mais um pouco.

//a tela que  vai receber o valor que for pesquisado. o bean dela é a informationHandHeldMB. ele tem um atributo do tipo Departamento (handDepartment)
<h:panelGrid columns="1" border="0"	style="font-family:verdana; font-size: 11px">
   <h:column>
	<h:inputText id="txtDp" style="width:300px" value="#{informationHandHeldMB.handDepartment.departmentName}" readonly="true" />
		<a4j:commandLink id="btnPesq" title="Pesquisar" onclick="Richfaces.showModalPanel('panel')" reRender="txtDp">
			<h:graphicImage id="image1" url="/images/search.gif" style="border:0; height: 17px;" />
                 </a4j:commandLink>
   </h:column>
</h:panelGrid>

<ui:include src="/pesquisas/pesqDepartment.xhtml">
	//aki ja tentei passando o bean cadastrado no faces-config, a propria classe e nada funciona.
     <ui:param name="bean" value="#{InformationHandHeldMB}" />
</ui:include>

//esse metodo ta no bean observador, o metodo update.
@Override
public void update(Observable o, Object arg) {
	if(arg instanceof HandDepartment){
		this.handDepartment = (HandDepartment)arg;			
	}
}


//essa tabela é construida por um ListDataModel(List<Departamento>)
//quando se clica na linha, ele executa o metodo getRowSelected para pegar o objeto da linha selecionada. Ate ai tudo bem.
<rich:dataTable width="99%" style="text-align:center; cursor: pointer" rows="10"
					value="#{pesquisaDepartment.dtModel}" var="dt" reRender="ds"
					id="simpletable"					
<a4j:support event="onRowClick" action="#{pesquisaDepartment.getRowSelected}" />

public String getRowSelected() {
		HandDepartment dp = (HandDepartment) dtModel.getRowData();
		if (dp != null)
			this.handDepartment = dp;
		
		notifyObservers(handDepartment);
		setChanged();
}

Até agora, o problema esta sendo que nao consegue instanciar a classe Observada (no caso, o bean do modal de pesquisa). Você ja conseguiu fazer assim alguma vez?

Obrigado pelo ajuda.

P

Vc não precisa implementar o padrão “a risca” não… Faz como eu te passei, passa o Managed Bean (com o include) como parâmetro para o xhtml de pesquisa e “injeta” no nele o resultado (no caso o Departament selecionado), sacou? Quando vc usa o include vc tem comunicação a nível de views e não tem nada a ver os Managed Bean. Ou seja, vc está passando um Managed Bean de um xhtml para o outro.

Para vc injetar, vc vai ter que ter o método setDepartamento (que será comum a todos as classes “observers”) como eu te exemplifiquei pelo código:

Paz e bem!

F

Bom dia Paulo. Cara o negocio ta feio aki… Olha as duvidas…
Eu nao intendi muito bem como funciona essa injeçao de dependencia. eu passo para a tela de pesquisa o bean que vai receber o valor, certo?

<ui:include src="/pesquisas/pesqDepartment.xhtml">
  <ui:param name="bean" value="#{informationHandHeldMB}" />
</ui:include>

Agora, quando eu vou setar o valor pesquisado no bean observador, vc colocou assim.

<f:setPropertyActionListener target="#{beanObserver.departamento}" value="#{departamento}" />

Esse “beanObserver” seria oq? uma interface q todos implementam para nao haver dependencia de tela? como ficaria isso?

Eu fiz um teste aki so para testar mesmo. Fiz uma dependecia, colocando assim.

<f:setPropertyActionListener target="#{informationHandHeldMB.departamento}" value="#{departamento}" />

Essa linha eu coloquei so para ver se ia rendenrizar o valor na tela que chamou o modal de pesquisa, so q isso tb nao aconteceu. Ele seta o valor no bean informationHandHeldMB, mas ele nao renderiza o valor na tela.

Cara, desculpa tanta ignorancia é pq esse é meu primeiro trabalho com JSF e ja me passaram isso pra fazer. Foi mals se ja tiver incomodando.

P

francis.junio:
Bom dia Paulo. Cara o negocio ta feio aki… Olha as duvidas…
Eu nao intendi muito bem como funciona essa injeçao de dependencia. eu passo para a tela de pesquisa o bean que vai receber o valor, certo?

<ui:include src="/pesquisas/pesqDepartment.xhtml">
  <ui:param name="bean" value="#{informationHandHeldMB}" />
</ui:include>

Agora, quando eu vou setar o valor pesquisado no bean observador, vc colocou assim.

<f:setPropertyActionListener target="#{beanObserver.departamento}" value="#{departamento}" />

Esse “beanObserver” seria oq? uma interface q todos implementam para nao haver dependencia de tela? como ficaria isso?

Eu fiz um teste aki so para testar mesmo. Fiz uma dependecia, colocando assim.

<f:setPropertyActionListener target="#{informationHandHeldMB.departamento}" value="#{departamento}" />

Essa linha eu coloquei so para ver se ia rendenrizar o valor na tela que chamou o modal de pesquisa, so q isso tb nao aconteceu. Ele seta o valor no bean informationHandHeldMB, mas ele nao renderiza o valor na tela.

Cara, desculpa tanta ignorancia é pq esse é meu primeiro trabalho com JSF e ja me passaram isso pra fazer. Foi mals se ja tiver incomodando.

Esse beanObserver é o mesmo bean que vc passou lá em cima. É pq eu não coloquei o mesmo nome. Seria assim:

<ui:include src="/pesquisas/pesqDepartment.xhtml">
  <ui:param name="beanObserver" value="#{informationHandHeldMB}" />
</ui:include>

Coloca alguma coisa assim:

<a4j:support event="oncomplete" reRender="txtDepartamento" />

no botão que chama o modal panel. Se vc já temo valor no Managed Bean, agora é só fazer o reRender.

Paz e bem!

F

Bom dia Paulo…
Consegui resolver agora cara… ate que enfim consegui…
A unica coisa que eu acho que ficou meio “gambiarra” é o seguinte. Eu tive que dar um reRender no “txtDp” pelo modalPanel. Eu nao consegui encontrar evento para fazer isso depois q o modal fecha. Entao o codigo ficou mais ou menos assim:

//codigo para abrir o modal
<a4j:commandLink id="btnPesq" title="Pesquisar"  action="#{pesquisaDepartment.destroy}"
  oncomplete="Richfaces.showModalPanel('panel')" ajaxSingle="true" reRender="panel">
  <h:graphicImage id="image1" url="/images/search.gif"
   style="border:0; height: 17px;" />
   //esse suporte aki nao serve para rendezirar o campo. o evento oncomplete executa antes mesmo do modal abrir.
  <a4j:support event="oncomplete" reRender="txtDp"/>
</a4j:commandLink>

<ui:include src="/pesquisas/pesqDepartment.xhtml">
	<ui:param name="beanObserver" value="#{informationHandHeldMB}" />
</ui:include>

Codigo do Modal Panel.

<div style="overflow: auto; width: 100%; height: 280px"><rich:dataTable
					width="99%" style="text-align:center; cursor: pointer"
					value="#{pesquisaDepartment.dtModel}" var="dt" id="simpletableDp"
					onRowMouseOver="this.style.backgroundColor='#F5E9D3'"
					onRowMouseOut="this.style.backgroundColor='#{a4jSkin.tableBackgroundColor}'">
					<a4j:support event="onRowClick"
						action="#{pesquisaDepartment.getRowSelected}" />
					<a4j:support event="onRowDblClick"
						oncomplete="Richfaces.hideModalPanel('panel')" reRender="txtDp">
						<f:setPropertyActionListener
							target="#{beanObserver.handDepartment}" value="#{dt}" />
					</a4j:support>
					<f:facet name="header">
						<rich:columnGroup>
							<rich:column>
								<h:outputText value="Código Departamento" />
							</rich:column>
							<rich:column>
								<h:outputText value="Descrição" />
							</rich:column>
						</rich:columnGroup>
					</f:facet>
					<rich:column>
						<h:outputText value="#{dt.departmentCode}" />
					</rich:column>
					<rich:column>
						<h:outputText value="#{dt.departmentName}" />
					</rich:column>
				</rich:dataTable></div>

Perceba que tive que dar o reRender no campo que recebe o valor pelo modalPanel.

<a4j:support event="onRowDblClick" oncomplete="Richfaces.hideModalPanel('panel')" reRender="txtDp">

Agora, todos as telas que forem receber esse valor, deve ter o campo com id = “txtDp”. Somente assim que consegui resolver. Achei que isso ficou meio gambiarra. Você tem alguma ideia para renderizar de outra forma sem ser pelo modalPanel?
Outra coisa tb eh que o bean de pesquisa deve ficar de sessao mesmo. Mas isso nao tem problemas.

Muito obrigado pela ajuda.
OBS.: Se nao tiver ideia para resolver esse “probleminha” acima, vou dar o topico como resolvido.

P

Olá, fiz um exemplo besta aqui e funcionou. Neste exemplo que fiz, eles ficam desacoplados.

welcomeJSF.jspx

&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;
&lt;jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
          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:t="http://myfaces.apache.org/tomahawk"
          xmlns:a4j="http://richfaces.org/a4j"
          xmlns:rich="http://richfaces.org/rich"
          xmlns="http://www.w3.org/1999/xhtml" version="2.0"&gt;

    &lt;f:view&gt;        
        &lt;a4j:form id="principal"&gt;
            &lt;h:outputText id="txtTeste" value="#{testeMB.mensagem}" /&gt;
            <br/>
            &lt;h:outputLink value="#" id="link"&gt;
                Show Modal Panel
                &lt;rich:componentControl for="panel" attachTo="link" operation="show" event="onclick"/&gt;                
            &lt;/h:outputLink&gt;
        &lt;/a4j:form&gt;

        &lt;ui:include src="/modal.jspx"&gt;
            &lt;ui:param name="bean" value="#{testeMB}" /&gt;
            &lt;ui:param name="componente" value="txtTeste" /&gt;
        &lt;/ui:include&gt;
    &lt;/f:view&gt;
&lt;/jsp:root&gt;

modal.jspx

&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;
&lt;jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
          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:t="http://myfaces.apache.org/tomahawk"
          xmlns:a4j="http://richfaces.org/a4j"
          xmlns:rich="http://richfaces.org/rich"
          xmlns="http://www.w3.org/1999/xhtml" version="2.0"&gt;

    &lt;rich:modalPanel id="panel" width="350" height="100"&gt;
        &lt;f:facet name="header"&gt;
            &lt;h:panelGroup&gt;
                &lt;h:outputText value="Modal Panel"&gt;&lt;/h:outputText&gt;
            &lt;/h:panelGroup&gt;
        &lt;/f:facet&gt;
        &lt;f:facet name="controls"&gt;
            &lt;h:panelGroup&gt;
                &lt;h:graphicImage value="/images/modal/close.png" styleClass="hidelink" id="hidelink"/&gt;
                &lt;rich:componentControl for="panel" attachTo="hidelink" operation="hide" event="onclick"/&gt;
            &lt;/h:panelGroup&gt;
        &lt;/f:facet&gt;
        <br/>
        &lt;a4j:form&gt;
            &lt;a4j:commandLink id="cmdLink" action="#{bean.teste}" value="Click me, please!" reRender="#{componente}"&gt;
                &lt;rich:componentControl for="panel" attachTo="cmdLink" operation="hide" event="onclick"/&gt;
            &lt;/a4j:commandLink&gt;
        &lt;/a4j:form&gt;
    &lt;/rich:modalPanel&gt;
&lt;/jsp:root&gt;

TesteMB.java

package teste;

/**
 *
 * @author paulo
 */
public class TesteMB {
    private String mensagem = null;

    public void teste() {
        setMensagem("Funcionou!!");
    }

    /**
     * @return the mensagem
     */
    public String getMensagem() {
        return mensagem;
    }

    /**
     * @param teste the mensagem to set
     */
    public void setMensagem(String mensagem) {
        this.mensagem = mensagem;
    }
}

Qual é o “segredo”? Passei como parâmetro o nome do componente que deve ser feito o reRender (linha 23 do welcomeJSF.jspx). No seu caso, vc pode colocar o nome de um panel que contenha os componentes que vc quer que atualize. Espero que resolve dessa vez. :slight_smile:

Paz e bem!

F

Boa tarde Paulo…
Desculpa a demora da resposta… To tao garrado aki que implementei oq vc falou e nao tive tempo de responder com a soluçao…
Deu tudo certo cara… Fiz do mesmo jeito que ficou seu exemplo, entao nem precisa postar a soluçao…

Muito obrigado pelo ajuda Paulo…

Abraços…

P

Que bom! Coloca resolvido aí então para ajudar o pessoal que precisa…

Paz e bem!

Criado 22 de junho de 2010
Ultima resposta 29 de jul. de 2010
Respostas 15
Participantes 2