JSF 2 + primefaces: desabilitar botão quando pressionado, habilitando após o retorno do método

Prezados(as),

JSF 2
Primefaces 3.3.1
Primefaces Mobile 0.9.3

Situação: quando o usuário clicar no botão Pesquisar, preciso que ele fique imediatamente disabled="true" e seu value alterado de "pesquisar" para "pesquisando…". Após o retorno do método presente no ActionListener dele, o botão volta a ficar disabled="false" e seu value = "Pesquisar".

Tentei das seguintes formas mas não obtive sucesso:

  1. http://stackoverflow.com/questions/9080005/how-to-enable-disable-a-jsf-command-button
  2. a mesma url acima, colocando immediate="true";
  3. Usando javascript, com função sendo chamada via onclick do botão. Neste caso acaba sem eu querer ocorrendo um refresh na página, fato que não quero que ocorra mas sim que seja atualizado apenas o botão.

Alguém pode ajudar ?

Segue o código:

<?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">
<f:view xmlns="http://www.w3.org/1999/xhtml"
        xmlns:f="http://java.sun.com/jsf/core"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:p="http://primefaces.org/ui"
        xmlns:pm="http://primefaces.org/mobile"
        contentType="text/html"
        lang="pt-br">   
    <h:head>
        <h:outputScript library="js" name="cad_pedido_venda.js" />
        <h:outputScript library="js" name="criaobj.js" />
        <h:outputScript library="js" name="tnaveg.js" />
        <h:outputScript library="js" name="tnaveg-jq.js" />
    </h:head>
    <pm:page title="Teste - Cadastro de Pedido de Venda">
        <f:facet name="preinit">
            <link type="text/css" rel="stylesheet" href="#{request.contextPath}/resources/css/cssLayout.css" />
            <link type="text/css" rel="stylesheet" href="#{request.contextPath}/resources/css/default_MOBILE.css" />
        </f:facet>
        <pm:view id="cad_pedido_venda01" swatch="a" >
            <pm:header title="Titulo da página" fixed="true" swatch="b" >
                <f:facet name="left"><p:button value="Retornar ao menu" icon="back" href="main_mobile_cad_pedido_venda.jsf" /></f:facet>
                <h:form>
                    <p:commandButton value="Sair" icon="back" disabled="#{pedidoVendaBean.desativar}" action="#{inicial.logout()}" />
                </h:form>
                Tela 1: Cadastro de Pedido de Venda - Escolha do cliente
            </pm:header>
            <pm:content>
                <h:form id="form_cad_pedido_venda01">
                    <p:growl id="msgs01" showDetail="true" />
                    <p:focus for="nome_cliente" />
                    <h:outputLabel value="Buscar cliente por: " />
                    <p:inputText id="nome_cliente" value="#{pedidoVendaBean.pedido.cliente.nome_cliente}" type="text" onkeydown="return ProxInput(this, event)"  onkeyup="this.value = this.value.toUpperCase();" />
                    <p:commandButton value="#{pedidoVendaBean.nomeBotao}" disabled="#{pedidoVendaBean.desativar}" actionListener="#{pedidoVendaBean.carregaListaClientes()}" update="clientes form_cad_pedido_venda01" immediate="true" >
                        <f:setPropertyActionListener value="false" target="#{pedidoVendaBean.desativar}"/>   
                        <f:setPropertyActionListener value="PESQUISANDO" target="#{pedidoVendaBean.nomeBotao}"/>   
                    </p:commandButton>                         
                    <p:dataTable id="clientes" var="cli" value="#{pedidoVendaBean.mediumClienteCgc}" 
                                 selectionMode="single" selection="#{pedidoVendaBean.clienteSelecionado}" 
                                 rowStyleClass="#{cli.saldoEmAtraso gt 0 ? 'vermelho' : cli.saldoEmAberto le 0 ? 'verde' : 'amarelo' }" 
                                 emptyMessage="Informe acima a primeira letra ou parte da razão social ou CNPJ. Em seguida clique no botão 'Pesquisar' e depois no cliente desejado." >
                        <p:ajax event="rowSelect" listener="#{pedidoVendaBean.onRowSelectCliente}" 
                                update=":form_cad_pedido_venda01:msgs01 :cad_pedido_venda02 :cad_pedido_venda03 :cad_pedido_venda04" />
                        <p:column>
                            <h:outputText value="#{cli.codigo_cliente} - #{cli.loja_cliente}" />  
                            <h:outputText value="#{cli.cgc}" >
                                <f:converter converterId="cnpjConverter" />
                            &lt;/h:outputText&gt;<br />
                            &lt;h:outputText value="#{cli.nome_cliente}" /&gt;<br />
                            &lt;h:outputText value="#{cli.nome_reduzido}" /&gt;<br />
                            &lt;h:outputText value="#{cli.bairro} #{cli.cidade}-#{cli.uf}" /&gt;<br />
                            &lt;h:outputText value="Email NF-e: #{cli.emailNFE}" /&gt;<br />
                        &lt;/p:column&gt;
                    &lt;/p:dataTable&gt;<br />
                    &lt;h:outputText value="Legenda: " style="font-weight: bold"/&gt;
                    &lt;h:outputText value="Sem títulos em aberto ou atraso; " styleClass="verde" /&gt;
                    &lt;h:outputText value="Saldo títulos a vencer &gt; 0; " styleClass="amarelo" /&gt;
                    &lt;h:outputText value="Saldo títulos em atraso &gt; 0." styleClass="vermelho" /&gt;
                &lt;/h:form&gt;
            &lt;/pm:content&gt;
        &lt;/pm:view&gt;

        &lt;pm:view id="cad_pedido_venda02" swatch="a" &gt;
...

No managedBean tenho :

public class PedidoVendaBean implements Serializable {
...
    private Boolean desativar = false;
    private String nomeBotao = "Pesquisar";

    public String getNomeBotao() {
        return nomeBotao;
    }

    public void setNomeBotao(String nomeBotao) {
        this.nomeBotao = nomeBotao;
    }

    public void setDesativar(Boolean desativar) {
        this.desativar = desativar;
    }

    public Boolean getDesativar() {
        return desativar;
    }
...

    public void carregaListaClientes() {
        this.desativar = true;
        this.nomeBotao = "pesquisando....";
.....
        this.nomeBotao = "Pesquisar";
        this.desativar = false;
}

Amigão,

no botão de pesquisar você pode utilizar o onclick chamando uma função js, ex:

seu botão em sua página,

... id="btnPesquisar" onclick="setPesquisando(this);" reRender="Região com resultado da pesquisa, btnPesquisar" ...

no javascript…

function setPesquisando(obj) {
	obj.setAttribute("setdisable", "1");
	setTimeout("setPesquisando_Action('" + obj.id + "')", 20);
}

function setPesquisando_Action(id) {
	var obj = document.getElementById(id);
	if (obj.getAttribute("setdisable") == "1") {
		if (labelAguarde == null) {
			labelAguarde = "Aguarde...";
		}

		obj.value = "Pesquisando";
		obj.disabled = true;
		obj.setAttribute("setdisable", "");
	}
}

att…
Emerson Dias

Olá Emerson,

Sem sucesso!

Ademais, não existe reRender no <p:commandButton>

Alguma outra alternativa ?

[quote=vicentedepaula]Olá Emerson,

Sem sucesso!

Ademais, não existe reRender no <p:commandButton>

Alguma outra alternativa ?[/quote]Existe o update que faz a mesma coisa.

Olá Herbert

Na mesma.

Ainda permite clicar mais de uma vez.

Vejo também que o javascript indicado tem o objetivo de desabilitar o botão, que não está funcionando. E se funcionar, como reabilitar o botão ?

Como havia dito no início, preciso desabilitar no primeiro clique e habilitar quando o método retornar. Ou seja, tenho quase certeza que devo usar o managedbean para realizar a mudança no
value e disabled deste botão, no ínicio e no final do método chamado no actionlistener.

Resta saber como.

[quote=vicentedepaula]Olá Herbert

Na mesma.

Ainda permite clicar mais de uma vez.

Vejo também que o javascript indicado tem o objetivo de desabilitar o botão, que não está funcionando. E se funcionar, como reabilitar o botão ?

Como havia dito no início, preciso desabilitar no primeiro clique e habilitar quando o método retornar. Ou seja, tenho quase certeza que devo usar o managedbean para realizar a mudança no
value e disabled deste botão, no ínicio e no final do método chamado no actionlistener.

Resta saber como.
[/quote]Eu nem olhei o código que o parceiro te indicou, mas para controlar objetos na tela por um ManagedBean você utiliza uma técnica chamada Binding.

Procure no google binding jsf button (por exemplo). De dentro do MB você conseguirá manipular tudo.

.

Estamos chegando lá!

Conforme indicação, utilizei o binding no p:commandbutton. O problema é que não apresenta na tela o value alterado no início método carregaListaClientes, conforme pode ser visto no código abaixo. Se eu colocar no update do p:commandbutton o id dele, começa a adicionar commandobutton dentro do existente.

Alguma indicação ?

XHTML:

            &lt;pm:view id="cad_pedido_venda01" swatch="a" &gt;
                &lt;pm:header title="Titulo Teste" fixed="true" swatch="b" &gt;
...
                &lt;/pm:header&gt;
                &lt;pm:content&gt;
                    &lt;h:form id="form_cad_pedido_venda01"&gt;
                        &lt;p:growl id="msgs01" showDetail="true" /&gt;
                        &lt;p:focus for="nome_cliente" /&gt;
                        &lt;h:outputLabel value="Buscar cliente por: " /&gt;
                        &lt;p:inputText id="nome_cliente" value="#{pedidoVendaBean.pedido.cliente.nome_cliente}" type="text" onkeydown="return ProxInput(this, event)"  onkeyup="this.value = this.value.toUpperCase();" /&gt;
                        &lt;p:commandButton actionListener="#{pedidoVendaBean.carregaListaClientes()}" binding="#{pedidoVendaBean.btnPesquisa}" update="clientes" /&gt;
                        &lt;p:dataTable id="clientes" var="cli" value="#{pedidoVendaBean.mediumClienteCgc}" 
                                     selectionMode="single" selection="#{pedidoVendaBean.clienteSelecionado}" 
                                     rowStyleClass="#{cli.saldoEmAtraso gt 0 ? 'vermelho' : cli.saldoEmAberto le 0 ? 'verde' : 'amarelo' }" 
                                     emptyMessage="Informe acima a primeira letra ou parte da razão social ou CNPJ. Em seguida clique no botão 'Pesquisar' e depois no cliente desejado." &gt;
                            &lt;p:ajax event="rowSelect" listener="#{pedidoVendaBean.onRowSelectCliente}" 
                                    update=":form_cad_pedido_venda01:msgs01 :cad_pedido_venda02 :cad_pedido_venda03 :cad_pedido_venda04" /&gt;
                            &lt;p:column&gt;
                                &lt;h:outputText value="#{cli.codigo_cliente} - #{cli.loja_cliente}" /&gt;&nbsp;&nbsp;
                                &lt;h:outputText value="#{cli.cgc}" &gt;
                                    &lt;f:converter converterId="cnpjConverter" /&gt;
                                &lt;/h:outputText&gt;<br />
                                &lt;h:outputText value="#{cli.nome_cliente}" /&gt;<br />
                                &lt;h:outputText value="#{cli.nome_reduzido}" /&gt;<br />
                                &lt;h:outputText value="#{cli.bairro} #{cli.cidade}-#{cli.uf}" /&gt;<br />
                                &lt;h:outputText value="Email NF-e: #{cli.emailNFE}" /&gt;<br />
                            &lt;/p:column&gt;
                        &lt;/p:dataTable&gt;<br />
                        &lt;h:outputText value="Legenda: " style="font-weight: bold"/&gt;
                        &lt;h:outputText value="Sem títulos em aberto ou atraso; " styleClass="verde" /&gt;
                        &lt;h:outputText value="Saldo títulos a vencer &gt; 0; " styleClass="amarelo" /&gt;
                        &lt;h:outputText value="Saldo títulos em atraso &gt; 0." styleClass="vermelho" /&gt;
                    &lt;/h:form&gt;
                &lt;/pm:content&gt;
            &lt;/pm:view&gt;
...

Managed Bean:

@SessionScoped
public class PedidoVendaBean implements Serializable {
...
    private CommandButton btnPesquisa = new CommandButton();

    public CommandButton getBtnPesquisa() {
        return btnPesquisa;
    }

    public void setBtnPesquisa(CommandButton btnPesquisa) {
        this.btnPesquisa = btnPesquisa;
    }
...
    public void carregaListaClientes() {
        this.btnPesquisa.setValue("Pesquisando...");
        this.btnPesquisa.setDisabled(true);
        System.out.println("oia eu aqui");

        this.clientela = this.pedido.getCliente().listagemClientes("N", this.pedido.getCliente().getNome_cliente(), "", "", "");
        this.mediumClienteCgc = new ClienteDataCgc(this.clientela);

        this.btnPesquisa.setDisabled(false);
        this.btnPesquisa.setValue("Pesquisar");
    }
...
}

Outro detalhe:

Com apenas um clique, ele entra umas 10 vezes no método do actionListener.

Porém, caso eu modifique da forma abaixo o commandbutton, ele executa apenas uma vez o método, mas persiste em atualizar o value de commandbutton:

&lt;p:commandButton id="btnPesquisa" value="#{pedidoVendaBean.btnPesquisa.value}" actionListener="#{pedidoVendaBean.carregaListaClientes()}" update="clientes" /&gt;

E se no update eu colocar “@this clientes” ele fica colocando um commandButton dentro do outro e por ai vai.

Pessoal,

outra tentativa sem sucesso:

&lt;p:inputText id="nome_cliente" value="#{pedidoVendaBean.pedido.cliente.nome_cliente}" type="text" onkeydown="return ProxInput(this, event)"  onkeyup="this.value = this.value.toUpperCase();" /&gt;
&lt;p:commandButton id="btnPesquisa" value="Pesquisar.." actionListener="#{pedidoVendaBean.carregaListaClientes()}" update="clientes" onclick = "this.value='Pesquisando...';" /&gt;

O p:inputText acima funciona beleza o onkeyup="this.value = this.value.toUpperCase();" />

Já o p:commandButton não funciona o onclick = “this.value=‘Pesquisando…’;”

Alguma sugestão?