JSF 2 fu: Componentes Ajax

Implemente componentes Ajaxified reutilizáveis com JSF 2

David Geary, membro de Grupo de Especialistas em Java™Server Faces JSF 2, começa uma série de novos artigos que oferecem uma cobertura detalhada da tecnologia JSF 2. Neste artigo, será possível aprender a integrar componentes compostos JSF 2 com o suporte da estrutura de desenvolvimento Ajax.

David Geary, President, Clarity Training, Inc.

David GearyO autor, palestrante e consultor David Geary é o presidente da Clarity Training, Inc. onde ensina desenvolvedores a implementarem aplicativos da Web usando JSF e Google Web Toolkit (GWT). Ele fez parte dos Grupos de Especialistas do JSTL 1.0 e do JSF 1.0/2.0, foi coautor do Exame de Certificação de Desenvolvedor da Web da Sun e contribuiu para projetos de software livre, incluindo o Apache Struts e o Apache Shale. Graphic Java Swing de David foi um dos livros de Java mais vendidos de todos os tempos e Core JSF (coescrito com Cay Horstman) é o livro de JSF mais vendido. David fala frequentemente em conferências e para grupos de usuários. É frequentador assíduo do tour de NFJS desde 2003, deu cursos na Java University e foi duas vezes votado como JavaOne rock star.



12/Mai/2010

Entre os vários novos recursos do JSF 2, provavelmente dois dos mais instigantes são os componentes compostos e o suporte Ajax. Mas sua força é mais aparente quando ambos são combinados, facilitando a implementação de componentes personalizados habilitados pelo Ajax com um mínimo de trabalho.

Sobre esta série

A série JSF fu é a sequência dos conceitos apresentados na introdução dos três artigos de David Geary com o mesmo nome. A série atual busca uma visão mais aprofundada do JSF 2 e de seu ecossistema circunvizinho. E oferece uma visão não convencional que mostra como algumas tecnologias Java EE, como Contextos e Injeção de Dependência, se integram com o JSF.

Neste artigo, vamos mostrar como implementar um componente de preenchimento automático que usa o Ajax para administrar sua lista de itens de preenchimento. E ao fazê-lo, veremos como é possível integrar o Ajax a seus próprios componentes compostos.

O código desta série é baseado no JSF 2 rodando em um contêiner corporativo, como o GlassFish ou Resin. A última seção deste artigo é um tutorial passo a passo para instalar e rodar o código do artigo com o GlassFish.

Um componente JSF personalizado de preenchimento automático

Famosos pelo campo de busca do Google, os campos de preenchimento automático (também conhecidos como caixas de sugestão), são um item básico de muitos aplicativos da Web. Eles também são um caso de uso típico do Ajax. Os campos de preenchimento automático vêm com a maioria das estruturas Ajax, como Scriptaculous e JQuery, como a coleção de componentes de preenchimento automático AjaxDaddy mostrada na Figura 1— (consulte Recursos) — atesta:

Figura 1. Componentes de preenchimento automático AjaxDaddy
Componentes de preenchimento automático AjaxDaddy

Este artigo vai explorar um modo de implementar um campo de preenchimento automático habilitado por Ajax com o JSF. Veremos como implementar o campo de preenchimento automático mostrado na Figura 2, que mostra uma lista curta de países fictícios (selecionados do artigo "Lista de países fictícios" da Wikipédia. Consulte Recursos):

Figura 2. O campo de preenchimento automático
O campo de preenchimento automático

A

Figura 3 e a Figura 4 mostram o campo de preenchimento automático em ação. Na Figura 3, quando Al é digitado no campo, a lista de países é reduzida a nomes que começam com estas duas letras:

Figura 3. Itens de preenchimento que começam com Al
Itens de preenchimento que começam com Al

Da mesma forma, a Figura 4 mostra os resultados quando Bar é digitado no campo. A lista só mostra os nomes de países que começam com Bar:

Figura 4. Itens de preenchimento que começam com Bar
Itens de preenchimento que começam com Bar

Usando o componente de preenchimento automático

Componentes compostos: Os conceitos básicos

Se você não estiver familiarizado com o uso ou a implementação de componentes compostos JSF 2, é possível achar uma introdução em "JSF 2 fu, Parte 2: Uso de modelos e componentes compostos."

O campo de preenchimento automático Locais é um componente composto JSF e é usado em um facelet, como mostrado na Listagem 1:

Listagem 1. O facelet
    <!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:h="http://java.sun.com/jsf/html"       
    xmlns:util="http://java.sun.com/jsf/composite/util">
    <h:head>      
    <title>#{msgs.autoCompleteWindowTitle}</title>  
    </h:head>     <h:body>   
    <div style="padding: 20px;">       
    <h:form>           
    <h:panelGrid columns="2">   
    #{msgs.locationsPrompt}               
    <util:autoComplete value="#{user.country}"      
    completionItems="#{autoComplete.countries}" />
    </h:panelGrid>         
    </h:form>       
    </div>    
    </h:body> 
    </html>

O facelet na Listagem 1 usa o componente composto autoComplete declarando um espaço de nomes apropriado —util— e usando o marcador associado ao componente, <util:autoComplete>.

Note os dois atributos do <util:autoComplete> marcador da Listagem 1:

  • value é a propriedade do país de um bean gerenciado cujo nome é user.
  • completionItems é o conjunto inicial de itens de preenchimento do campo.

A classe User é um bean gerenciado simples, obviamente inventado apenas para esta ocasião. Seu código é mostrado na Listagem 2:

Listagem 2. A classe User
    package com.corejsf;  import java.io.Serializable;  
    import javax.inject.Named;  
    import javax.enterprise.context.SessionScoped;  
    @Named() @SessionScoped 
    public class User implements Serializable
    {   private String country;   
    public String getCountry() 
    { return country; }   
    public void setCountry(String country)
    { this.country = country; } }

Observe a anotação @Named, que junto com @SessionScoped, instancia um bean gerenciado nomeadouser e o coloca no escopo da sessão na primeira vez que o JSF encontra #{user.country} em um facelet. A única referência deste aplicativo a #{user.country} ocorre na Listagem 1, onde eu especifico a country propriedade do user bean gerenciado como o valor do componente <util:autoComplete>.

A

Listagem 3 mostra a classe AutoComplete que define a propriedade countries que especifiquei como a lista do componente de preenchimento automático dos itens de preenchimento:

Listagem 3. Os itens de preenchimento
    package com.corejsf;  
    import java.io.Serializable;  
    import javax.enterprise.context.ApplicationScoped; import javax.inject.Named; 
    @Named @ApplicationScoped public class AutoComplete implements Serializable
    {    public String[] getLocations() 
    {       return new String[]
    {     		 
    "Abari", "Absurdsvanj", "Adjikistan", "Afromacoland",     		  
    "Agrabah", "Agaria", "Aijina", "Ajir", "Al-Alemand",     		 
    "Al Amarja", "Alaine", "Albenistan", "Aldestan",     		
    "Al Hari", "Alpine Emirates", "Altruria",     		 
    "Allied States of America", "BabaKiueria", "Babalstan",     		 
    "Babar's Kingdom","Backhairistan", "Bacteria",     		 
    "Bahar", "Bahavia", "Bahkan", "Bakaslavia",     		 
    "Balamkadar", "Baki", "Balinderry", "Balochistan",     		 
    "Baltish", "Baltonia", "Bataniland, Republic of",     		  
    "Bayview", "Banania, Republica de", "Bandrika",     		
    "Bangalia", "Bangstoff", "Bapetikosweti", "Baracq",     		 
    "Baraza", "Barataria", "Barclay Islands",     		
    "Barringtonia", "Bay View", "Basenji",      
    };    } }

Isso é tudo sobre o uso do componente de preenchimento automático. Agora vejamos como ele funciona.


Como funciona o componente de preenchimento automático

O componente de preenchimento automático é um componente composto JSF 2, que como a maioria dos componentes compostos, é implementado em um arquivo XHTML. O componente consiste em uma entrada de texto e uma caixa de listagem, e algum JavaScript. Inicialmente, o style da caixa de listagem é display: none, que faz a caixa de listagem ficar invisível.

O componente de preenchimento automático responde a três eventos:

  • keyup eventos na entrada de texto
  • blur (perdendo o foco) eventos na entrada de texto
  • change (seleção) eventos na caixa de listagem

Quando o usuário digita a entrada de texto, o componente de preenchimento automático chama uma função JavaScript para cada evento keyup. Esta função reúne os eventos de batida de tecla para fazer não mais que uma chamada Ajax a cada 350 ms. Assim, em resposta a keyup eventos na entrada de texto, o componente de preenchimento automático faz uma chamada Ajax, no máximo a cada 350 ms, para o servidor. (Tudo isso para impedir os datilógrafos rápidos de inundar o servidor com chamadas Ajax. Na prática, os eventos reunidos podem ser superavaliados neste caso, mas oferecem uma oportunidade de ilustrar eventos reunidos no JavaScript, que em geral é uma ferramenta útil.)

Quando o usuário seleciona um item na caixa de listagem, o componente de preenchimento automático faz outra chamada Ajax ao servidor.

Ambas a entrada de texto e a caixa de listagem têm listeners anexados a elas, que fazem a maior parte do trabalho significativo no servidor durante as chamadas Ajax. Em resposta a eventos keyup, o listener da entrada de texto atualiza os itens de preenchimento da caixa de listagem. Em resposta aos eventos de seleção da caixa de listagem, o listener dessa caixa copia o item selecionado para a entrada de texto e a oculta.

Agora que temos uma boa ideia de como o componente de preenchimento automático funciona, estamos prontos para dar uma olhada em sua implementação.


Implementando o componente de preenchimento automático

A implementação do componente de preenchimento automático consiste nestes artefatos:

  • Um componente composto
  • Um punhado de funções JavaScript
  • Um listener de mudança de valor que atualiza itens de preenchimento

Vamos começar com o componente composto na Listagem 4:

Listagem 4. O componente autoComplete
    <ui:composition xmlns="http://www.w3.org/1999/xhtml"     
    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:composite="http://java.sun.com/jsf/composite">         
    <!-- INTERFACE -->    
    <composite:interface>     
    <composite:attribute
    name="value" 
    required="true"/>      
    <composite:attribute 
    name="completionItems" 
    required="true"/>    
    </composite:interface>       
    <!-- IMPLEMENATION -->              
    <composite:implementation>       
    <div id="#{cc.clientId}">        
    <h:outputScript library="javascript"             
    name="prototype-1.6.0.2.js" target="head"/>                  
    <h:outputScript library="javascript"            
    name="autoComplete.js" target="head"/>               
    <h:inputText id="input" value="#{cc.attrs.value}"            
    onkeyup="com.corejsf.updateCompletionItems(this, event)"           
    onblur="com.corejsf.inputLostFocus(this)"          
    valueChangeListener=
    "#{autocompleteListener.valueChanged}"/>                
    <h:selectOneListbox id="listbox" style="display: none"          
    valueChangeListener=
    "#{autocompleteListener.completionItemSelected}">                    
    <f:selectItems 
    value="#{cc.attrs.completionItems}"/>           
    <f:ajax render="input"/>                   
    </h:selectOneListbox>       <div>    
    </composite:implementation>    
    </ui:composition>

Três coisas estão acontecendo na seção de implementação da Listagem 4. Primeiro, o componente faz chamadas Ajax em resposta a keyup eventos na entrada de texto, e oculta a caixa de listagem quando a entrada de texto perde o foco em virtude de funções JavaScript atribuídas a keyup e eventos blur na entrada de texto.

Segundo, o componente faz chamadas Ajax em resposta a eventos change na caixa de listagem com o marcador <f:ajax> do JSF 2. Quando o usuário faz uma seleção na caixa de listagem, o JSF faz uma chamada Ajax para o servidor e atualiza o valor da entrada de texto quando a chamada Ajax retorna.

Agrupa componentes compostos em um <div>

O componente composto da Listagem 4 agrupa sua implementação em um <div> com o identificador de cliente do componente composto. Isso permite que outros componentes façam referência ao componente de preenchimento automático por meio de seu ID de cliente. Por exemplo, outro componente pode querer executar ou apresentar um ou mais componentes de preenchimento automático durante uma chamada Ajax.

Terceiro, tanto a entrada de texto quanto a caixa de listagem têm métodos de listener de mudança de valor anexados a elas, assim quando o JSF fizer chamadas Ajax em resposta ao usuário que digita a entrada de texto, o JSF invoca o listener de mudança de valor da entrada de texto no servidor. Quando o usuário seleciona um item na caixa de listagem, o JSF faz uma chamada Ajax para o servidor e invoca o listener de mudança de valor da caixa de listagem.

A

Listagem 5 mostra o JavaScript usado pelo componente de preenchimento automático:

Listagem 5. O JavaScript
    if (!com)    var com = {} 
    if (!com.corejsf) {    
    var focusLostTimeout    com.corejsf = 
    {       errorHandler : function(data) 
    {          
    alert("Error occurred during Ajax call: " + data.description) 
    },  
    updateCompletionItems : 
    function(input, event) {          
    var keystrokeTimeout           
    jsf.ajax.addOnError(com.corejsf.errorHandler)          
    var ajaxRequest = function() {             
    jsf.ajax.request(input, event, {               
    render: com.corejsf.getListboxId(input),               
    x: Element.cumulativeOffset(input)[0],               
    y: Element.cumulativeOffset(input)[1]                     
    + Element.getHeight(input)             })   
    }           window.clearTimeout(keystrokeTimeout) 
    keystrokeTimeout = window.setTimeout(ajaxRequest, 350)   
    },
    inputLostFocus : function(input) {         
    var hideListbox = function() {          
    Element.hide(com.corejsf.getListboxId(input))      
    }  
    focusLostTimeout = window.setTimeout(hideListbox, 200)  
    },        getListboxId : function(input)
    {          var clientId = new String(input.name)    
    var lastIndex = clientId.lastIndexOf(':')       
    return clientId.substring(0, lastIndex) + ':listbox' 
    }    } }

O JavaScript da Listagem 5 consiste em três funções que eu coloquei dentro de um espaço de nomes chamado com.corejsf. Eu implementei o espaço de nomes (que é tecnicamente um objeto literal do JavaScript) para evitar que alguém acidentalmente (ou não) derrote quaisquer de minhas três funções.

Se essas funções não estivessem ocultas dentro de com.corejsf, alguém poderia implementar sua própria função updateCompletionItems, substituindo assim minha implementação pela dele. É possível que alguma biblioteca JavaScript possa implementar uma função chamada updateCompletionItems, mas vale a pena apostar que ninguém vai aparecer com com.corejsf.updateCompletionItems. (Em retrospectiva, deixar o com para ficar com corejsf.updateCompletionItems provavelmente teria sido suficiente, mas às vezes é fácil se exceder.)

Assim, o que fazem as funções? A função updateCompletionItems() faz um pedido Ajax ao servidor — chamando a função do JSF jsf.ajax.request()— pedindo que o JSF só apresente o componente da caixa de listagem quando a chamada Ajax retornar. A função updateCompletionItems() também passa dois parâmetros extras para o jsf.ajax.request(): as coordenadas x e y do canto superior esquerdo da caixa de listagem. A função jsf.ajax.request() transforma esses parâmetros de função em parâmetros de pedido, que ela envia com a chamada Ajax.

O JSF chama a função inputLostFocus() quando a entrada de texto perder o foco. Esta função simplesmente oculta a caixa de listagem, usando o objeto do Protótipo Element.

Ambos updateCompletionItems() e inputLostFocus() armazenam sua funcionalidade em uma função. Então eles programam suas funções para executar em 350 ms e 200 ms, respectivamente. Em outras palavras, cada função tem um trabalho a fazer, mas ela atrasa aquela tarefa durante 350 ms ou 200 ms. A entrada de texto é atrasada após um evento keyup, de forma que o método updateCompletionItems() envie o pedido Ajax uma vez a cada 350 ms no máximo. A ideia é que se o usuário for um datilógrafo (extremamente!) rápido, seja possível evitar inundar o servidor com chamadas Ajax.

A função inputLostFocus, chamada quando a entrada de texto perde o foco, atrasa sua tarefa em 200 ms. Este atraso é necessário porque o valor será copiado para fora da caixa de listagem quando a chamada Ajax retornar, e essa caixa deve estar visível para que isso funcione.

Finalmente, note a função getListBoxId(). Esta função auxiliar obtém o identificador do cliente da caixa de listagem a partir do identificador do cliente da entrada de texto. A função pode fazer isso porque está em conluio com o componente autoComplete da Listagem 4. O componente autoComplete atribui input e listbox como os identificadores de componente para a entrada de texto e a caixa de listagem respectivamente, assim a função getListBoxId() somente corta fora input e acrescenta listbox para ir do identificador do cliente da entrada de texto para o da caixa de listagem.

A

Listagem 6 mostra a implementação do listener que reúne tudo:

Listagem 6. O listener
    package com.corejsf; 
    import java.io.Serializable; 
    import java.util.ArrayList; 
    import java.util.List; import java.util.Map; 
    import javax.enterprise.context.SessionScoped;
    import javax.faces.component.UIInput; 
    import javax.faces.component.UISelectItems;
    import javax.faces.component.UISelectOne; 
    import javax.faces.context.FacesContext; 
    import javax.faces.event.ValueChangeEvent; 
    import javax.inject.Named; 
    @Named @SessionScoped public class
    AutocompleteListener implements Serializable 
    {    private static String COMPLETION_ITEMS_ATTR = "corejsf.completionItems";  
    public void valueChanged(ValueChangeEvent e) {     
    UIInput input = (UIInput)e.getSource();       
    UISelectOne listbox = (UISelectOne)input.findComponent("listbox"); 
    if (listbox != null) {        
    UISelectItems items = (UISelectItems)listbox.getChildren().get(0);
    Map<String, Object> attrs = listbox.getAttributes();    
    List<String> newItems = getNewItems((String)input.getValue(), 
    getCompletionItems(listbox, items, attrs));          
    items.setValue(newItems.toArray());       
    setListboxStyle(newItems.size(), attrs);  
    }    }    
    public void completionItemSelected(ValueChangeEvent e) 
    {      UISelectOne listbox = (UISelectOne)e.getSource();   
    UIInput input = (UIInput)listbox.findComponent("input");        
    if(input != null) {        
    input.setValue(listbox.getValue());      }  
    Map<String, Object> attrs = listbox.getAttributes(); 
    attrs.put("style", "display: none");    }     
    private List<String> 
    getNewItems(String inputValue, String[] completionItems) 
    {       List<String> newItems = new ArrayList<String>(); 
    for (String item : completionItems) {      
    String s = item.substring(0, inputValue.length());
    if (s.equalsIgnoreCase(inputValue))          
    newItems.add(item);       }           
    return newItems;    }      
    private void setListboxStyle(int rows, Map<String, Object> attrs)
    {       if (rows > 0) {      
    Map<String, String> reqParams = FacesContext.getCurrentInstance()   
    .getExternalContext().getRequestParameterMap();       
    attrs.put("style", "display: inline; position: absolute; left: "   
    + reqParams.get("x") + "px;" + " top: " + reqParams.get("y") + "px");    
    attrs.put("size", rows == 1 ? 2 : rows);       } 
    else        
    attrs.put("style", "display: none;");    }   
    private String[] getCompletionItems(UISelectOne listbox, 
    UISelectItems items, Map<String, Object> attrs) 
    {          Strings] completionItems = (String[])
    attrs.get(COMPLETION_ITEMS_ATTR); 
    if (completionItems == null) {            
    completionItems = (String[])items.getValue(); 
    attrs.put(COMPLETION_ITEMS_ATTR, completionItems);        
    }       return completionItems;    } }

O JSF invoca o método do listener valueChanged() durante chamadas Ajax em resposta a eventos keyup na entrada de texto. Este método cria um novo conjunto de itens de preenchimento, e então define os itens da caixa de listagem para este novo conjunto. O método também define atributos de estilo para a caixa de listagem, que determinam se a caixa de listagem é exibida quando a chamada Ajax retorna.

O método setListboxStyle() na Listagem 6 usa os valores de parâmetros de pedido x e y que especifiquei quando fiz a chamada Ajax da Listagem 5.

O JSF invoca o único outro método público do listener completionItemSelected() durante chamadas Ajax, em resposta a eventos de seleção na caixa de listagem. Este método copia o valor da caixa de listagem para a entrada de texto e oculta a caixa de listagem.

Note que o método valueChanged() também armazena os itens de preenchimento originais em um atributo da caixa de listagem. Como cada componente autoComplete mantém sua própria lista de itens de preenchimento, múltiplos componentes autoComplete podem coexistir pacificamente na mesma página sem prejudicar os itens de preenchimento uns dos outros.


Rodando os exemplos com GlassFish e Eclipse

O código desta série de artigos é mais bem adequado a um contêiner JEE 6, como GlassFish ou Resin. É possível fazer as coisas funcionarem com um contêiner de servlet como o Tomcat, mas observe a parte de "fazer as coisas funcionarem". Como minha meta é extrair todo o potencial do JSF 2 e JEE 6, e não abordar questões de configuração, vamos ficar com o GlassFish v3.

No restante deste artigo, vamos mostrar como rodar a amostra de código usando o GlassFish v3 e Eclipse. As instruções aqui também serão suficientes para o código do resto desta série de artigos. (Estou usando o Eclipse 3.4.1, assim quanto mais perto for possível ficar disso ao rodar os exemplos, melhor.)

A

Figura 5 mostra a estrutura de diretórios encontrada no código deste artigo. (Visite Download para obter o código agora.) Há um diretório de preenchimento automático que contém o aplicativo e um diretório da área de trabalho vazio para o Eclipse.

Figura 5. Código fonte no download deste artigo
Código fonte no download deste artigo

Agora que já temos o código, estamos quase prontos para rodá-lo. Primeiro é preciso ter o plug-in do GlassFish Eclipse, que está disponível em https://glassfishplugins.dev.java.net, mostrado na Figura 6:

Figura 6. O plug-in do GlassFish Eclipse
O plug-in do GlassFish Eclipse

Basta seguir as instruções de instalação do plug-in, e estaremos prontos para começar.

Para instalar o código deste artigo, crie um projeto de Web Dinâmica no Eclipse. É possível fazer isso no menu File > New: se o projeto de Web Dinâmica não for exibido ali, selecione Other, e na caixa de diálogo resultante abra a pasta Web e selecione Dynamic Web Project, como mostrado na Figura 7:

Figura 7. Criando um projeto de Web Dinâmica
Criando um projeto de Web Dinâmica

A próxima etapa é configurar o projeto. Faça as seguintes seleções na primeira tela do assistente New Dynamic Web Project, como mostrado na Figura 8:

  1. Em Project contents, deixe a caixa Use default desmarcada. No campo Directory, digite (ou navegue até) o diretório autoComplete da amostra de código.
  2. Para Target Runtime, selecione GlassFish v3 Java EE 6.
  3. Para Dynamic Web Module version, digite 2.5.
  4. Para Configuration, selecione Default Configuration for GlassFish v3 Java EE 6.
  5. Em EAR Membership, deixe a caixa Add project to an EAR desmarcada e digite autoCompleteEAR no campo EAR Project Name: .
Figura 8. Configurando o aplicativo, etapa 1
Configurando o aplicativo, etapa 1

Clique em Next, e então digite os valores mostrados na Figura 9:

  1. Para Context Root: digite autoComplete.
  2. Para Content Directory: digite web.
  3. Para Java Source Directory: digite src/java. Deixe a caixa Generate deployment descriptor desmarcada.
Figura 9. Configurando o aplicativo, etapa 2
Configurando o aplicativo, etapa 2

Agora devemos ter um projeto autoComplete visível na tela do Project Explorer do Eclipse, como mostrado na Figura 10:

Figura 10. O projeto autoComplete
O projeto autoComplete

Agora selecione o projeto, clique com o botão direito nele, e selecione Run on Server, como mostrado na Figura 11:

Figura 11. Rodando no servidor do Eclipse
Rodando no servidor do Eclipse

Selecione GlassFish v3 Java EE 6 na lista de servidores da caixa de diálogo Run On Server, mostrada na Figura 12:

Figura 12. Selecionando o GlassFish
Selecionando o GlassFish

Clique em Finish. O Eclipse deve iniciar o GlassFish, e subsequentemente o aplicativo autoComplete, como mostrado na Figura 13:

Figura 13. Rodando no Eclipse
Rodando no Eclipse

Conclusão

Com o JSF 2 fica fácil criar poderosos componentes personalizados habilitados pelo Ajax. Não é preciso implementar um componente ou renderizador baseado em Java, ou declarar aquele componente ou renderizador em XML, nem integrar JavaScript de terceiros para fazer chamadas Ajax. Com o JSF 2 basta criar um componente composto, com markup quase idêntico a qualquer facelet JSF 2, e talvez acrescentar um pequeno JavaScript ou código Java, e voilà! — temos um componente personalizado ideal que facilita a entrada de dados para os usuários de seu aplicativo.

Na próxima parte do JSF fu, vamos discutir mais aspectos da implementação de componentes personalizados JSF Ajaxified, como integrar o marcador <f:ajax> para que seus componentes personalizados possam participar do Ajax iniciado por outros.


Download

DescriçãoNomeTamanho
Sample code for this articlej-jsf2fu-0410-src.zip39KB

Recursos

Aprender

Obter produtos e tecnologias

  • JSF: Faça o download do JSF 2.0.

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java
ArticleID=489291
ArticleTitle=JSF 2 fu: Componentes Ajax
publish-date=05122010