quinta-feira, 8 de março de 2012

Como Limpar um InputText no JSF a Partir do Managed Bean (Controller)

O objetivo aqui é simplesmente criar um formulário para inserir itens numa lista e atualizar os componentes automaticamente, sem ter que carregar toda a página. Em outras palavras, ao pressionar o botão para fazer a inserção, é lista é atualizada com o novo item e o campo de entrada do título item é limpo. Para tanto, utilizei JSF 2 e Primefaces 3.1. A solução foi encontrada no fórum Code Ranch, onde dois membros postaram duas soluções (Prakash Jebaraj & Gregg Bolinger) diferentes.

Solução 1
O código abaixo foi extraído dos meus testes e usei componentes do Primefaces. Aqui, somente uma entrada de texto e um botão para inserir fazem parte do foumulário para exemplificação.

<h:form id="idForm">
   <p:inputtext id="idNome" value="#{myManagedBean.nome}"/>
   <p:commandbutton actionlistener="#{myManagedBean.inserirNome(event)}" immediate="true" update="idNome" value="Inserir"/>
</h:form>

Ao pressionar o botão, o método inserirNome do meu Managed Bean é chamado, a página não é recarregada e o campo de entrada de texto é limpo.

@ManagedBean(name = "myManagedBean")
@SessionScoped
public class ManagedBean {
    
    private String nome;

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome= nome;
    }

    public void inserirNome(ActionEvent event) {
         // TODO: inserir nome em alguma lista ou base de dados
        FacesContext facesContext = FacesContext.getCurrentInstance();
        UIViewRoot uiViewRoot = facesContext.getViewRoot();
        HtmlInputText inputText = (HtmlInputText) uiViewRoot.findComponent("idForm:idNome");
        inputText.setSubmittedValue("");
        this.setNome("");
    }
}

Note que na linha 19 do código acima, a string usada para localizar o HtmlInputText é a concatenação dos identificadores da árvore de componentes da página, separado por dois pontos. Assim,  qualquer alteração nos identificadores ou na hierarquida dos componentes da página vai diretamente afetar esta solução.

Solução 2
A segunda solução não é muito diferente da primeira. Aqui, a alteração dos identificadores de componentes da página não tem impacto na solução porque o campo de entrada de texto é explicitamente associado a um elemento de interface gráfica do lado o servidor. Veja abaixo, no componente
inputText, a propriedade binding em uso, onde é feita esta associação.


<h:form id="idForm">
   <p:inputtext id="idNome" value="#{myManagedBean.nome}" binding="#{myManagedBean.uiNome}"/>
   <p:commandbutton actionlistener="#{myManagedBean.inserirNome(event)}" immediate="true" update="idNome" value="Inserir"/>
</h:form>

Desta forma, o Managed Bean precisa ter um atributo do tipo UIInput, com seus métodos get e set. Já o método inserirNome,invocado pelo actionListener do botão de inserir, tem menos código para fazer a limpeza do campo de entrada.

@ManagedBean(name = "myManagedBean")
@SessionScoped
public class ManagedBean {
    
    private String nome;
    private UIInput uiNome;

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome= nome;
    }

    public String getUiNome() {
        return uiNome;
    }

    public void setUiNome(String uiNome) {
        this.uiNome= uiNome;
    }

    public void inserirNome(ActionEvent event) {
        // TODO: inserir nome em alguma lista ou base de dados        
        this.getUiNome().setSubmittedValue("");
        this.setNome(""); 
    }
}

Esta segunda solução não está diretamente associada ao identificadores dos elementos da interface gráfica, assim, qualquer alteração de identificadores de componentes da página não vai afetar o código.

Referências:
http://www.coderanch.com/t/210589/JSF/java/Clearing-forms
https://cwiki.apache.org/confluence/display/MYFACES/Clear+Input+Components
http://www.guj.com.br/java/92758-resolvidolimpar-o-resultado-da-consulta-e-os-campos-do-formulario-com-jsf