[RESOLVIDO] PrimeFaces 3 - Propriedade editable do SelectOneMenu não "existe"

13 respostas
M

Fala galera, é o seguinte estou com um problema no uso do SelectOneMenu, está quase tudo certo, porém, quero que o SelectOneMenu permita ao usuário digitar ou pelo menos começar a digitar o texto e então o valor ser selecionado/sugerido.

Exemplificando:
Tenho quase 6000 cidades em um componente p:selectOneMenu e o usuário já sabe que a cidade é, por exemplo, São Paulo. Ao invés de ir até o registro São Paulo através do uso do mouse, ela então começa a digitar a String “Sã”, por exemplo, e a combo sugere ou seleciona o primeiro registro com essa ocorrência.

Problema:
O componente p:selectOneMenu não aceita a propriedade editable, de forma que o usuário apenas consegue selecionar (com o mouse) não consegue digitar ou sequer navegar/selecionar com as “setas”. No ShowCase do Primefaces existe um componente selectOneMenu configurado para ser editável e aceitar digitação, porém, não está funcionando, no meu caso, o netBeans acusa a seguinte mensagem:

Mensagem de Erro do NetBeans:
The attribute editable is not defined in the component’s interface

PrimeFaces Exemplo:

<h:outputText value="Editable: " />  
<p:selectOneMenu value="#{pprBean.city}" effect="fold" editable="true">  
      <f:selectItem itemLabel="Select One" itemValue="" />  
      <f:selectItems value="#{pprBean.cities}" />  
</p:selectOneMenu>

Meu Código:

<p:selectOneMenu value="#{cidadeMB.cidade.uf}" effect="fade"  editable="true"
            required="true" requiredMessage="O Campo Unidade Federativa é obrigatório.">
      <f:selectItems value="#{cidadeMB.ufs}" var="uf" itemLabel="#{uf.nome}" itemValue="#{uf}"/>
</p:selectOneMenu>

Já tentei utilizar o p:autoComplete, porém, tem alguns erros que não consegui resolver, e ele não “sugeriu/completou”.

No mais é isso, Agradeço!!!

13 Respostas

G

Oi, com o p:selectOneMenu acho que vc não vai conseguir fazer isso, vc teria que usar o p:autoComplete mesmo, quais foram os erros ao utilizar o p:autoComplete?

M

Então, com o p:autoComplete o que está acontecendo é o seguinte: só consigo digitar algo se eu for de componente em componente do formulário (via TAB) até chegar nele, ou seja, caso o usuário clique direto no componente (autoComplete) ele não deixa digitar. Mesmo quando vou de componente em componente (via TAB) ele só me permite digitar uma letra, e então realiza as sugestões a partir da letra digitada, porém, preciso que o autoComplete realize o filtro com mais letras.

PrimeFaces - ShowCase

<p:autoComplete id="dd" dropdown="true" value="#{autoCompleteBean.txt6}"   
                    completeMethod="#{autoCompleteBean.complete}" />

Meu Código:

<p:autoComplete id="i_cidadeUf" dropdown="true" value="#{cidadeMB.cidade.uf}"
                                required="true" requiredMessage="O Campo Uf é obrigatório"
                                var="uf" itemLabel="#{uf.nome}" itemValue="#{uf}" effect="fade"
                                queryDelay="0" readonly="false"
                                completeMethod="#{cidadeMB.completaUf}" converter="ufConverter" />

Nesse contexto são mostradas todas as UFs, porém, ocorre os erros que supracitei.

De antemão agradeço!!

G

Quando ocorre esse problema não mostra nenhum erro no console?

Qual versão do primefecas vc ta usando? Eu uso esse componente com a versão 2 sem maiores problemas.

M

Então, não aparece nenhum erro/aviso no console!

Minha versão do PrimeFaces é a 3.0.

G

Quando vc vai direto para o componente ele não fica habilitado para edição? Se fica, quando vc digita algo nele o método completaUf está sendo chamado?
como esta seu método completaUf no bean?

M

Quando vou direto ao componente ele não permite edição, porém, o método completaUf é chamado porque é ele quem retorna as Unidades da Federação (UFs) disponíveis, mesmo que não tenha nenhum filtro.

Quando vou de componente em componente (só funciona via TAB) ele me permite editar o componente, porém, apenas por alguns instantes, normalmente, um usuário digitaria uma letra ou duas no máximo, com o tempo que o componente fica disponível.

Código do Método completaUf()

public List<Uf> completaUf(String query) {
      if (!query.isEmpty()) {
            List<Uf> sugestoes = new ArrayList<Uf>();
            for (Uf uf : getUfs()) {
                if (uf.getNome().toLowerCase().startsWith(query.toLowerCase())) {
                    sugestoes.add(uf);
                }
            }
            return sugestoes;
        }
        return getUfs();
}

Agradeço desde já!!

G

cara isso é muito estranho, não tem alguma coisa que ta desabilitando o componente para edição? Pela lógica o método completaUf só deveria ser chamado ao digitar alguma coisa no componente, mas vc ta dizendo que ele é chamado mesmo não permitindo edição, isso não poderia ta ocorrendo.

M

Tipo é isso que está acontecendo, tanto que tive que realizei uma condição: se a variavel query estiver vazia então retorna tudo.

O funcionamento é até estável no caso de seleção (selecionar um registro), porém, a ideia é permitir a edição para que o usuário tenha mais agilidade.

G

Você poderia postar o código completo da sua página xhtml?

M
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">

    <ui:composition template="/pages/template/templateCadastro.xhtml">
        <ui:param name="title" value="Cidades" />
        <ui:param name="idTabela" value="cidades" />

        <ui:define name="botaoNovo">
            <p:commandButton id="btnNovo" value="Novo" update="novoRegistro"
                             onclick="dlgNovo.show()" process="@this"
                             immediate="true" action="#{cidadeMB.limpaCidade}" />
            <p:commandButton id="btnVoltar" value="Voltar"
                             onclick="window.location='${pageContext.request.contextPath}/webRMX/pages/index.jsf'"
                             type="button" ajax="false"/>
        </ui:define>

        <ui:define name="table">
            <p:dataTable id="cidades" var="cidade" value="#{cidadeMB.dataModel}"
                         paginator="true" rows="10" selection="#{cidadeMB.cidadeSelecionada}"
                         selectionMode="single" resizableColumns="true"
                         emptyMessage="Sem Registros." rowsPerPageTemplate="10,20,30"
                         rowKey="#{cidade.id}">

                <p:ajax event="rowSelect" listener="#{cidadeMB.onRowSelect}" update="detalhes" />

                <f:facet name="header">
                    Lista de Cidades
                </f:facet>

                <p:column headerText="Id" sortBy="#{cidade.id}" filterBy="#{cidade.id}" >
                    #{cidade.id}
                </p:column>

                <p:column headerText="Nome" sortBy="#{cidade.nome}" filterBy="#{cidade.nome}">
                    #{cidade.nome}
                </p:column>

                <p:column headerText="UF" sortBy="#{cidade.uf.sigla}" filterBy="#{cidade.uf.sigla}">
                    #{cidade.uf.sigla}
                </p:column>

                <p:column>
                    <p:commandButton id="selectButton" oncomplete="dlgDetalhes.show()" icon="ui-icon-search" title="Detalhes">  
                        <f:setPropertyActionListener value="#{cidade}" target="#{cidadeMB.cidade}" />  
                    </p:commandButton>
                    <p:commandButton id="updateButton" oncomplete="dlgAlterar.show()" icon="ui-icon-arrowrefresh-1-w" title="Alterar" update="alterar" >
                        <f:setPropertyActionListener value="#{cidade}" target="#{cidadeMB.cidade}" />  
                    </p:commandButton>
                    <p:commandButton id="deleteButton" oncomplete="dlgExcluir.show()" icon="ui-icon-close" title="Excluir">
                        <f:setPropertyActionListener value="#{cidade}" target="#{cidadeMB.cidade}" />  
                    </p:commandButton>
                </p:column>

            </p:dataTable>
        </ui:define>

        <ui:define name="formDetalhes">
            <h:panelGrid columns="2">
                <h:outputText value="Id:" />
                <h:outputText value="#{cidadeMB.cidade.id}" />
                <h:outputText value="Nome*:" />
                <h:outputText value="#{cidadeMB.cidade.nome}" />
                <h:outputText value="UF*:" />
                <h:outputText value="#{cidadeMB.cidade.uf.sigla}" />
                <h:outputText value="Data de Criação:" />
                <h:outputText value="#{cidadeMB.cidade.criacao.time}" >
                    <f:convertDateTime type="date" dateStyle="short"/>
                </h:outputText>
                <h:outputText value="Data de Modificação:"/>
                <h:outputText value="#{cidadeMB.cidade.modificacao.time}" >
                    <f:convertDateTime type="date" dateStyle="short"/>
                </h:outputText>
                <h:outputText value="Usuário Criador:" />
                <h:outputText value="#{cidadeMB.cidade.criador.nome}" />
            </h:panelGrid>
        </ui:define>

        <ui:define name="formCadastro">
            <h:panelGrid columns="2">
                <h:outputText value="Nome*:" />
                <p:inputText id="i_cidadeNome" value="#{cidadeMB.cidade.nome}" maxlength="45" 
                             required="true" requiredMessage="O Campo Nome é obrigatório."/>
                <h:outputText value="UF*:" />

                <p:selectOneMenu value="#{cidadeMB.cidade.uf}" effect="fold" editable="true"
                                 required="true" requiredMessage="O Campo Unidade Federativa é obrigatório.">
                    <f:selectItems value="#{cidadeMB.ufs}"/>
                </p:selectOneMenu>

                <p:commandButton id="i_btnSalvar" value="Salvar" update="cidades growl"
                                 action="#{cidadeMB.salvar}" oncomplete="handleComplete(args)" />
                <p:commandButton id="i_btnCancelar" value="Cancelar" onclick="dlgNovo.hide()"
                                 type="button"  />
            </h:panelGrid>
        </ui:define>

        <ui:define name="formAlterar">
            <h:panelGrid columns="2">
                <h:outputText value="Nome*:" />
                <p:inputText id="a_cidadeNome" value="#{cidadeMB.cidade.nome}" maxlength="45" 
                             required="true" requiredMessage="O Campo nome é obrigatório."/>
                <h:outputText value="UF*:" />
                <p:inputText id="a_cidadeUf" value="#{cidadeMB.cidade.uf.sigla}" maxlength="20" 
                             required="true" requiredMessage="O Campo UF é obrigatório."/>

                <p:commandButton id="a_btnAlterar" value="Alterar" update="cidades growl"
                                 oncomplete="handleComplete(args)"
                                 actionListener="#{cidadeMB.alterar}" />
                <p:commandButton id="a_btnCancelar" value="Cancelar" onclick="dlgAlterar.hide()"
                                 type="button" ajax="false"/>
            </h:panelGrid>
        </ui:define>

        <ui:define name="formDeletar">
            <p:commandButton id="btnSim" value="Sim"
                             oncomplete="dlgExcluir.hide()" ajax="false"
                             actionListener="#{cidadeMB.deletar}" update="cidades" />
        </ui:define>
    </ui:composition>

</html>
G

e onde está o código com o autocomplete?
Vi que vc está colocando editable=“true” no seu p:selectOneMenu, essa propriedade não existe, vc só vai conseguir o que quer usando o p:autoComplete.
Outra coisa vc implementou um Converter para Uf?

M

Me desculpe código errado, tenho deixado esse código aí como oficial até que o autoComplete funcione.

Quanto à classe Uf, Sim, eu implementei um converter para ela.

Segue o código correto:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">

    <ui:composition template="/pages/template/templateCadastro.xhtml">
        <ui:param name="title" value="Cidades" />
        <ui:param name="idTabela" value="cidades" />

        <ui:define name="botaoNovo">
            <p:commandButton id="btnNovo" value="Novo" update="novoRegistro"
                             onclick="dlgNovo.show()" process="@this"
                             immediate="true" action="#{cidadeMB.limpaCidade}" />
            <p:commandButton id="btnVoltar" value="Voltar"
                             onclick="window.location='${pageContext.request.contextPath}/webRMX/pages/index.jsf'"
                             type="button" ajax="false"/>
        </ui:define>

        <ui:define name="table">
            <p:dataTable id="cidades" var="cidade" value="#{cidadeMB.dataModel}"
                         paginator="true" rows="10" selection="#{cidadeMB.cidadeSelecionada}"
                         selectionMode="single" resizableColumns="true"
                         emptyMessage="Sem Registros." rowsPerPageTemplate="10,20,30"
                         rowKey="#{cidade.id}">

                <p:ajax event="rowSelect" listener="#{cidadeMB.onRowSelect}" update="detalhes" />

                <f:facet name="header">
                    Lista de Cidades
                </f:facet>

                <p:column headerText="Id" sortBy="#{cidade.id}" filterBy="#{cidade.id}" >
                    #{cidade.id}
                </p:column>

                <p:column headerText="Nome" sortBy="#{cidade.nome}" filterBy="#{cidade.nome}">
                    #{cidade.nome}
                </p:column>

                <p:column headerText="UF" sortBy="#{cidade.uf.sigla}" filterBy="#{cidade.uf.sigla}">
                    #{cidade.uf.sigla}
                </p:column>

                <p:column>
                    <p:commandButton id="selectButton" oncomplete="dlgDetalhes.show()" icon="ui-icon-search" title="Detalhes">  
                        <f:setPropertyActionListener value="#{cidade}" target="#{cidadeMB.cidade}" />  
                    </p:commandButton>
                    <p:commandButton id="updateButton" oncomplete="dlgAlterar.show()" icon="ui-icon-arrowrefresh-1-w" title="Alterar" update="alterar" >
                        <f:setPropertyActionListener value="#{cidade}" target="#{cidadeMB.cidade}" />  
                    </p:commandButton>
                    <p:commandButton id="deleteButton" oncomplete="dlgExcluir.show()" icon="ui-icon-close" title="Excluir">
                        <f:setPropertyActionListener value="#{cidade}" target="#{cidadeMB.cidade}" />  
                    </p:commandButton>
                </p:column>

            </p:dataTable>
        </ui:define>

        <ui:define name="formDetalhes">
            <h:panelGrid columns="2">
                <h:outputText value="Id:" />
                <h:outputText value="#{cidadeMB.cidade.id}" />
                <h:outputText value="Nome*:" />
                <h:outputText value="#{cidadeMB.cidade.nome}" />
                <h:outputText value="UF*:" />
                <h:outputText value="#{cidadeMB.cidade.uf.sigla}" />
                <h:outputText value="Data de Criação:" />
                <h:outputText value="#{cidadeMB.cidade.criacao.time}" >
                    <f:convertDateTime type="date" dateStyle="short"/>
                </h:outputText>
                <h:outputText value="Data de Modificação:"/>
                <h:outputText value="#{cidadeMB.cidade.modificacao.time}" >
                    <f:convertDateTime type="date" dateStyle="short"/>
                </h:outputText>
                <h:outputText value="Usuário Criador:" />
                <h:outputText value="#{cidadeMB.cidade.criador.nome}" />
            </h:panelGrid>
        </ui:define>

        <ui:define name="formCadastro">
            <h:panelGrid columns="2">
                <h:outputText value="Nome*:" />
                <p:inputText id="i_cidadeNome" value="#{cidadeMB.cidade.nome}" maxlength="45" 
                             required="true" requiredMessage="O Campo Nome é obrigatório."/>
                <h:outputText value="UF*:" />

                <p:autoComplete id="i_cidadeUf" dropdown="true" value="#{cidadeMB.cidade.uf}"  
                                required="true" requiredMessage="O Campo Uf é obrigatório"  
                                var="uf" itemLabel="#{uf.nome}" itemValue="#{uf}" effect="fade"
                                completeMethod="#{cidadeMB.completaUf}" converter="ufConverter" />  

                <p:commandButton id="i_btnSalvar" value="Salvar" update="cidades growl"
                                 action="#{cidadeMB.salvar}" oncomplete="handleComplete(args)" />
                <p:commandButton id="i_btnCancelar" value="Cancelar" onclick="dlgNovo.hide()"
                                 type="button"  />
            </h:panelGrid>
        </ui:define>

        <ui:define name="formAlterar">
            <h:panelGrid columns="2">
                <h:outputText value="Nome*:" />
                <p:inputText id="a_cidadeNome" value="#{cidadeMB.cidade.nome}" maxlength="45" 
                             required="true" requiredMessage="O Campo nome é obrigatório."/>
                <h:outputText value="UF*:" />
                <p:inputText id="a_cidadeUf" value="#{cidadeMB.cidade.uf.sigla}" maxlength="20" 
                             required="true" requiredMessage="O Campo UF é obrigatório."/>

                <p:commandButton id="a_btnAlterar" value="Alterar" update="cidades growl"
                                 oncomplete="handleComplete(args)"
                                 actionListener="#{cidadeMB.alterar}" />
                <p:commandButton id="a_btnCancelar" value="Cancelar" onclick="dlgAlterar.hide()"
                                 type="button" ajax="false"/>
            </h:panelGrid>
        </ui:define>

        <ui:define name="formDeletar">
            <p:commandButton id="btnSim" value="Sim"
                             oncomplete="dlgExcluir.hide()" ajax="false"
                             actionListener="#{cidadeMB.deletar}" update="cidades" />
        </ui:define>
    </ui:composition>

</html>
Está na linha 90.

De toda forma agradeço!!

M

Problema com o AutoComplete resolvido!

O problema estava na utilização do AutoComplete dentro de um Dialog, ou seja, fora do Dialog, funciona perfeitamente, porém, dentro não funcionava.

A solução foi atualizar o primefaces para o 3.0 M4.

Há uma discurssão sobre o problema nesse link: http://code.google.com/p/primefaces/issues/detail?id=3208

Quanto ao componente SelectOneMenu a propriedade editable não existia realmente na versão do primefaces, basta atualizá-lo!

Agradeço ao geraldo.vec pelo empenho em ajudar-me!!!

Criado 14 de fevereiro de 2012
Ultima resposta 5 de mar. de 2012
Respostas 13
Participantes 2