JSF 2 fu, Parte 3: Manipulação de Eventos, JavaScript e Ajax

Aprimore componentes compostos usando mais recursos novos do JSF 2

Membro do Grupo de Especialistas do Java™Server Faces (JSF) 2, David Geary conclui sua série em três partes sobre os novos recursos do JSF 2. Descubra como usar o novo modelo de eventos e o suporte integrado da estrutura para Ajax para tornar seus componentes reutilizáveis ainda mais poderosos.

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.



14/Jul/2009

Um dos pontos principais do sucesso de vendas do JSF é ser uma estrutura baseada em componentes. Isso significa que é possível implementar componentes que você, ou outras pessoas, possam reutilizar. Esse poderoso mecanismo de reutilização foi, em grande parte, considerado inconsequente no JSF 1, pois era muito difícil de implementar componentes.

Como foi visto na Parte 2, no entanto, o JSF 2 facilita a implementação de componentes — sem nenhum código Java e nenhuma configuração — com um novo recurso chamado componentes compostos. Esse recurso pode muito bem ser a parte mais importante do JSF 2, pois, finalmente, realiza o potencial de componentes JSF.

Neste terceiro artigo final sobre JSF 2, mostrarei como estender o recurso do componente composto usando os novos recursos Ajax e de manipulação de eventos, também introduzidos no JSF 2, com as seguintes dicas para obter o máximo do JSF 2:

  • Dica 1: Dividir em componentes
  • Dica 2: Usar Ajax
  • Dica 3: Mostrar progresso

Na primeira dica, irei revisar de forma resumida dois componentes discutidos extensivamente na Parte 2. Nas dicas seguintes, mostrarei como transformar esses componentes usando o Ajax e a manipulação de eventos.

Dica 1: Dividir em Componentes

O aplicativo places, que introduzi na Parte 1, contém diversos componentes compostos. Um deles é o componente map , que exibe um mapa de um endereço, completo com um menu suspenso de nível de zoom, conforme mostrado na Figura 1:

Figura 1. O Componente map do Aplicativo places
O Componente map

A lista truncada do componente map é mostrada na Lista 1:

Lista 1. O Componente map
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<html xmlns="http://www.w3.org/1999/xhtml"
    ...
    xmlns:composite="http://java.sun.com/jsf/composite"
    xmlns:places="http://java.sun.com/jsf/composite/components/places">

   <!-- INTERFACE -->
   <composite:interface>
     <composite:attribute name="title"/>
   </composite:interface>

   <!-- IMPLEMENTATION -->
   <composite:implementation">
     <div class="map">
       ...
       <h:panelGrid...>
         <h:panelGrid...>
            <h:selectOneMenu onchange="submit()"
                 value="#{cc.parent.attrs.location.zoomIndex}"
                 valueChangeListener="#{cc.parent.attrs.location.zoomChanged}"
                 style="font-size:13px;font-family:Palatino">
            
              <f:selectItems value="#{places.zoomLevelItems}"/>
                           
            </h:selectOneMenu>               
          </h:panelGrid>
        </h:panelGrid>   
        
        <h:graphicImage url="#{cc.parent.attrs.location.mapUrl}" 
          style="border: thin solid gray"/>  
       ...
      
     </div>
   ...
       
  </composite:implementation>    
</html>

Uma das melhores coisas sobre componentes é que é possível substituí-los por alternativas mais poderosas sem perturbar nenhuma funcionalidade circundante. Por exemplo, na Figura 2, coloquei o componente image da Lista 1 com um componente Google Maps, cortesia de GMaps4JSF (consulte Recursos):

Figura 2. Imagem de Mapa de GMaps4JSF
Componente map GMaps4JSF

O código atualizado (e truncado) para o componente map é mostrado na Lista 2:

Lista 2. Substituindo a Imagem do Mapa por um Componente GMaps4JSF
<h:selectOneMenu onchange="submit()"value="#{cc.parent.attrs.location.zoomIndex}"
              valueChangeListener="#{cc.parent.attrs.location.zoomChanged}"
              style="font-size:13px;font-family:Palatino">
     
  <f:selectItems value="#{places.zoomLevelItems}"/>
                    
</h:selectOneMenu>   

...         

<m:map id="map" width="420px" height="400px" 
     address="#{cc.parent.attrs.location.streetAddress}, ..." 
     zoom="#{cc.parent.attrs.location.zoomIndex}"
     renderOnWindowLoad="false">
     
  <m:mapControl id="smallMapCtrl" 
              name="GLargeMapControl" 
          position="G_ANCHOR_TOP_RIGHT"/>
          
  <m:mapControl  id="smallMapTypeCtrl" name="GMapTypeControl"/>                  
  <m:marker id="placeMapMarker"/>     
    
</m:map>

Para usar um componente GMaps4JSF, substituí a tag <h:graphicImage> por uma tag <m:map> do conjunto de componentes GMaps4JSF. Também foi simples enganchar o componente GMaps4JSF no menu suspenso de zoom, simplesmente especificando a propriedade backing-bean correta para, da tag <m:map> , o atributo zoom .

Falando em níveis de zoom, observe que quando um usuário altera o nível de zoom, forço o envio de um formulário com, do <h:selectOneMenu>, o atributo onchange , conforme mostrado na primeira linha parcialmente em negrito na Lista 1. O envio desse formulário aciona o ciclo de vida do JSF, que, por fim, envia o novo valor para o nível de zoom na propriedade zoomIndex de um bean location armazenado no componente pai composto. Essa propriedade bean é ligada ao componente de entrada, na primeira linha da Lista 2.

Como não especifiquei nenhuma navegação para o envio de formulário associado à mudança do nível de zoom, o JSF atualiza a mesma página após tratar do pedido, redesenhando a imagem do mapa para refletir o novo nível de zoom. No entanto, a atualização da página também redesenha toda a página, apesar de a única mudança estar na imagem do mapa. Na Dica 2: Usar Ajax, mostrarei como usar Ajax para redesenhar somente a imagem em resposta para uma mudança de nível de zoom.

O Componente login

Outro componente usado no aplicativo places é o componente login . A Figura 3 mostra o componente login em ação:

Figura 3. O Componente login
O Componente login

A Lista 3 mostra a marcação que criou o componente login mostrado na Figura 3:

Lista 3. loginMinimalista: Apenas os Atributos Necessários
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:util="http://java.sun.com/jsf/composite/components/util">

  <util:login loginAction="#{user.login}"
              managedBean="#{user}"/>
                
</ui:composition>

O componente login possui apenas dois atributos necessários:

  • loginAction: Um método de ação de login
  • managedBean: Um bean gerenciado com propriedades de nome e senha

O bean gerenciado especificado na Lista 3 é mostrado na Lista 4:

Lista 4. User.groovy
package com.clarity

import javax.faces.context.FacesContext
import javax.faces.bean.ManagedBean
import javax.faces.bean.SessionScoped

@ManagedBean()
@SessionScoped

public class User {
  private final String VALID_NAME     = "Hiro"
  private final String VALID_PASSWORD = "jsf"

  private String name, password;

  public String getName() { name }
  public void setName(String newValue) { name = newValue }

  public String getPassword() { return password }
  public void setPassword(String newValue) { password = newValue }

  public String login() {
    "/views/places"
  }

  public String logout() {
    name = password = nameError = null
    "/views/login"
  }
}

O bean gerenciado na Lista 4 é um bean Groovy. Usar Groovy em vez de a linguagem Java não é um ganho substancial neste caso, exceto por me liberar do trabalho penoso dos pontos e vírgulas e instruções de retorno. No entanto, na seção Validação da Dica 2, mostrarei uma razão mais convincente para o uso de Groovy para o bean gerenciado User .

Na maioria das vezes, você irá querer configurar os componentes de login integralmente com prompts e texto de botão, conforme mostrado na Figura 4:

Figura 4. Um Componente login Integralmente Configurado
Componente login integralmente configurado

A Lista 5 mostra a marcação que gerou o componente login na Figura 4:

Lista 5. Configurando o Componente login
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:util="http://java.sun.com/jsf/composite/components/util">

  <util:login loginPrompt="#{msgs.loginPrompt}"
               namePrompt="#{msgs.namePrompt}"
           passwordPrompt="#{msgs.passwordPrompt}"
          loginButtonText="#{msgs.loginButtonText}"
              loginAction="#{user.login}"
              managedBean="#{user}"/>

</ui:composition>

Na Lista 5, obtenho cadeias de caracteres para prompts e o texto do botão de login de um pacote de recursos.

A Lista 6 define o componente login :

Lista 6. Definindo o Componente login
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<!-- Usage:

  <util:login loginPrompt="#{msgs.loginPrompt}"
               namePrompt="#{msgs.namePrompt}"
           passwordPrompt="#{msgs.passwordPrompt}"
          loginButtonText="#{msgs.loginButtonText}"
              loginAction="#{user.login}"
              managedBean="#{user}">

    <f:actionListener for="loginButton"
                     type="com.clarity.LoginActionListener"/>

  </util:login>

  managedBean must have two properties: name and password. 

  The loginAction attribute must be an action method that takes no
  arguments and returns a string. That string is used to navigate
  to the page the user sees after logging in.

  This component's loginButton is accessible so that you can
  add action listeners to it, as depicted above. The class specified
  in f:actionListener's type attribute must implement the
  javax.faces.event.ActionListener interface.

 -->

<html xmlns="http://www.w3.org/1999/xhtml"
    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>

    <!-- PROMPTS -->
    <composite:attribute name="loginPrompt"/>
    <composite:attribute name="namePrompt"/>
    <composite:attribute name="passwordPrompt"/>

    <!--  LOGIN BUTTON -->
    <composite:attribute name="loginButtonText"/>

    <!-- loginAction is called when the form is submitted -->
    <composite:attribute name="loginAction"
             method-signature="java.lang.String login()"
                     required="true"/>

    <!-- You can add listeners to this actionSource:  -->
    <composite:actionSource name="loginButton" targets="form:loginButton"/>

    <!-- BACKING BEAN -->
    <composite:attribute name="managedBean" required="true"/>
  </composite:interface>

  <!-- IMPLEMENTATION -->
  <composite:implementation>
    <div class="prompt">
      #{cc.attrs.loginPrompt}
    </div>

    <!-- FORM -->
    <h:form id="form">
      <h:panelGrid columns="2">

        <!-- NAME AND PASSWORD FIELDS -->
        #{cc.attrs.namePrompt}
        <h:inputText id="name"
                  value="#{cc.attrs.managedBean.name}"/>
    
        #{cc.attrs.passwordPrompt}
        <h:inputSecret id="password" size="8"
          value="#{cc.attrs.managedBean.password}"/>

      </h:panelGrid>

      <p>
        <!-- LOGIN BUTTON -->
        <h:commandButton id="loginButton"
          value="#{cc.attrs.loginButtonText}"
          action="#{cc.attrs.loginAction}"/>
      </p>
    </h:form>
  </composite:implementation>
</html>

Como o componente map , o componente login poderia usar um upgrade do Ajax. Na próxima dica, sob Validação, mostrarei como incluir a validação do Ajax no componente login.


Dica 2: Usar Ajax

Ajax geralmente requer duas etapas que geralmente não são executadas para pedidos HTTP não-Ajax: processamento parcial de formulários no servidor e uma renderização parcial subsequente do Document Object Model (DOM) no cliente.

Processamento e Renderização Parciais

O JSF 2 suporta o processamento parcial e a renderização parcial, dividindo o ciclo de vida do JSF em duas partes lógicas distintas: executação e renderização. A Figura 5 realça a parte da execução:

Figura 5. A Parte da Execução do Ciclo de Vida do JSF
A Parte da Execução do Ciclo de Vida do JSF

A Figura 6 realça a parte da renderização do ciclo de vida do JSF:

Figura 6. A Parte da Renderização do Ciclo de Vida do JSF
A Parte da Renderização do Ciclo de Vida do JSF

A ideia por trás das partes de execução e renderização do ciclo de vida é simples: é possível especificar componentes que o JSF executa (processa) no servidor e componentes que o JSF renderiza quando uma chamada do Ajax retorna. Isso é feito com <f:ajax>, que é novo para o JSF 2, conforme mostrado na Lista 7:

Lista 7. Um Menu de Zoom do Ajax
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<h:selectOneMenu id="menu"
     value="#{cc.parent.attrs.location.zoomIndex}"
     style="font-size:13px;font-family:Palatino">

  <f:ajax event="change" execute="@this" render="map"/>
  <f:selectItems value="#{places.zoomLevelItems}"/>

</h:selectOneMenu>

<m:map id="map"...>

A Lista 7 é uma modificação do menu mostrada na primeira linha da Lista 2: Removi o atributo onchange da Lista 2 e incluí uma tag <f:ajax> . Essa tag <f:ajax> especifica:

  • O evento que aciona a chamada do Ajax
  • Um componente para executar no servidor
  • Um componente para renderizar no cliente

Quando o usuário seleciona um item no menu de zoom, o JSF faz uma chamada do Ajax ao servidor. Subsequentemente, o JSF passa o menu através da parte da execução do ciclo de vida (@this expressa o componente circundante do <f:ajax>) e atualiza zoomIndex do menu durante a fase Atualizar Valores do Modelo do ciclo de vida. Quando a chamada do Ajax retorna, o JSF renderiza o componente do mapa, que usa o índice de zoom (novo configurado) para redesenhar o mapa, e agora você tem um menu de zoom com Ajax com a inclusão de uma linha de XHTML.

Mas as coisas podem ficar ainda mais simples, pois o JSF fornece valores padrão para os atributos event e execute .

Cada componente do JSF tem um evento padrão que aciona chamadas do Ajax se você integrar uma tag <f:ajax> dentro da tag do componente. Para menus, esse evento é o evento change . Isso significa que posso me livrar do atributo, de <f:ajax>, event na Lista 7. O padrão para o atributo, de <f:ajax>, execute é @this, que significa o componente circundante de <f:ajax>. Neste exemplo, esse componente é o menu, portanto, também posso me livrar do atributo execute .

Usando valores de atributos padrão para <f:ajax>, posso reduzir a Lista 7 para a Lista 8:

Lista 8. Versão Mais Simples de um Menu de Zoom do Ajax
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<h:selectOneMenu id="menu"
     value="#{cc.parent.attrs.location.zoomIndex}"
     style="font-size:13px;font-family:Palatino">

  <f:ajax render="map"/>
  <f:selectItems value="#{places.zoomLevelItems}"/>

</h:selectOneMenu>

<m:map id="map"...>

Isso mostra como é fácil incluir Ajax em seus componentes com o JSF 2. É claro que o exemplo anterior é bem simples: estou simplesmente redesenhando somente o mapa, em vez de toda a página quando o usuário seleciona um nível de zoom. Algumas operações, como validar campos individuais em um formulário, são mais complicada, portanto, em seguida vou lidar com esse caso de uso.

Validação

É uma boa ideia validar campos e fornecer feedback imediato quando um usuário sai de um campo usando tabulação. Por exemplo, na Figura 7, estou usando o Ajax para validar o campo de nome:

Figura 7. Validação do Ajax
Validação do Ajax

A marcação para o campo de nome é mostrada na Lista 9:

Lista 9. O Campo de Nome
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<h:panelGrid columns="2">
  #{cc.attrs.namePrompt}
  <h:panelGroup>
    <h:inputText id="name" value="#{cc.attrs.managedBean.name}"
       valueChangeListener="#{cc.attrs.managedBean.validateName}">

       <f:ajax event="blur" render="nameError"/>

     </h:inputText>

     <h:outputText id="nameError"
       value="#{cc.attrs.managedBean.nameError}"
       style="color: red;font-style: italic;"/>
  </h:panelGroup>
  ...
</h:panelGrid>

Novamente, uso <f:ajax>, mas desta vez o evento padrão para entradas —change— não funcionará, portanto, especifico blur para o evento que aciona a chamada do Ajax. Quando o usuário sai do campo de nome usando tabulação, o JSF faz uma chamada do JSF ao servidor e executa o componente de entrada name através da parte da execução do ciclo de vida. Isso significa que o JSF chamará o listener de mudança de valor da entrada name especificado na Lista 9 durante a fase Validações de Processo do ciclo de vida. A Lista 10 mostra esse listener de mudança de valor:

Lista 10. O Método validateName()
package com.clarity

import javax.faces.context.FacesContext
import javax.faces.bean.ManagedBean
import javax.faces.bean.SessionScoped
import javax.faces.event.ValueChangeEvent
import javax.faces.component.UIInput

@ManagedBean()
@SessionScoped

public class User {
  private String name, password, nameError;

  ...

  public void validateName(ValueChangeEvent e) {
    UIInput nameInput = e.getComponent()
    String name = nameInput.getValue()

    if (name.contains("_"))   nameError = "Name cannot contain underscores"
    else if (name.equals("")) nameError = "Name cannot be blank"
    else                      nameError = "" 
  }
  
  ...
}

O listener de mudança de valor — o método, do bean gerenciado user , validateName()— valida o campo de nome e atualiza a propriedade do bean gerenciado user , nameError .

Após a chamada do Ajax retornar, em virtude do atributo render da tag <f:ajax> na Lista 9, o JSF renderiza a saída de nameError . Essa saída mostra a propriedade do bean gerenciado user , nameError .

Validação de Diversos Campos

Na subseção anterior, mostrei como executar a validação do Ajax em um único campo. Às vezes, no entanto, é necessário validar diversos campos ao mesmo tempo. Por exemplo, a Figura 8 mostra o aplicativo places validando os campos de nome e senha juntos:

Figura 8. Validando Diversos Campos
Validando Diversos Campos

Valido os campos de nome e senha juntos quando o usuário envia o formulário, portanto, não preciso do Ajax para este exemplo. Em vez disso, usarei o novo sistema de eventos do JSF 2, conforme mostrado na Lista 11:

Lista 11. Usando <f:event>
<h:form id="form" prependId="false">

  <f:event type="postValidate"
       listener="#{cc.attrs.managedBean.validate}"/>
  ...
</h:form>

<div class="error" style="padding-top:10px;">
  <h:messages layout="table"/>
</div>

Na Lista 11, uso <f:event>, que — como <f:ajax> — é novo para o JSF 2. A tag <f:event> é semelhante a <f:ajax> em outro sentido, também: é simples de usar.

Você coloca uma tag <f:event> dentro da tag do componente e quando o evento especificado (especificado com o atributo type ) ocorre para esse componente, o JSF chama um método, especificado com o atributo listener . Portanto, em termos gerais, a tag <f:event> da Lista 11 significa que: Após validar o formulário, chame o método validate() no bean gerenciado que o usuário passou para esse componente composto. Esse método é mostrado na Lista 12:

Lista 12. O Método validate()
package com.clarity

import javax.faces.context.FacesContext
import javax.faces.bean.ManagedBean
import javax.faces.bean.SessionScoped
import javax.faces.event.ValueChangeEvent
import javax.faces.component.UIInput

@ManagedBean()
@SessionScoped

public class User {
  private final String VALID_NAME     = "Hiro";
  private final String VALID_PASSWORD = "jsf";

  ...

  public void validate(ComponentSystemEvent e) {
    UIForm form = e.getComponent()
    UIInput nameInput = form.findComponent("name")
    UIInput pwdInput = form.findComponent("password")

    if ( ! (nameInput.getValue().equals(VALID_NAME) &&
        pwdInput.getValue().equals(VALID_PASSWORD))) {

      FacesContext fc = FacesContext.getCurrentInstance()
      fc.addMessage(form.getClientId(),
        new FacesMessage("Name and password are invalid. Please try again."))
      fc.renderResponse()
    }
  }

  ...
}

JSF passa ao método validate() na Lista 12 um evento de sistema de componentes, a partir do qual o método obtém uma referência ao componente ao qual o evento se aplica — o formulário de login. A partir do formulário, uso o método findComponent() para obter os componentes nome e senha. Se os valores desses componentes não forem Hiro e jsf, respectivamente, armazeno uma mensagem no contexto de faces e informo o JSF para continuar imediatamente para a fase Renderizar Resposta do ciclo de vida. Dessa forma, evito que a fase Atualizar Valores do Modelo, que enviaria o nome e a senha inválidos para o modelo (consulte a Figura 5).

Você deve ter percebido que os métodos de validação na Lista 10 e na Lista 12 são gravados em Groovy. Diferentemente da Lista 4, onde a única vantagem de usar Groovy era ficar livre de pontos e vírgulas e instruções de retorno, o código Groovy na Lista 10 e na Lista 12 me libera de efetuar cast. Por exemplo, na Lista 10, ComponentSystemEvent.getComponent() e UIComponent.findComponent() retornam o tipo UIComponent. Com a linguagem Java, seria necessário efetuar cast dos valores de retorno desses métodos. Groovy efetua cast para mim.


Dica 3: Mostrar Progresso

Em Usar Ajax, eu mostrei como usar Ajax no menu de zoom para o componente map , de forma que o aplicativo places redesenha somente a parte do mapa da página quando o usuário altera o nível de zoom. Outro caso de uso comum do Ajax é fornecer algum feedback ao usuário de que um evento Ajax está em progresso, conforme mostrado na Figura 9:

Figura 9. Uma Barra de Progresso
Uma Barra de Progresso

Na Figura 9, substituí o menu de zoom com uma GIF animada que é exibida enquanto a chamada do Ajax progride. Quando a chamada do Ajax for concluída, substituo o indicador de progresso com o menu de zoom. A Lista 13 mostra como é feito:

Lista 13. Monitorando um Pedido do Ajax
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<h:selectOneMenu id="menu"
     value="#{cc.parent.attrs.location.zoomIndex}"
     style="font-size:13px;font-family:Palatino">

  <f:ajax render="map" onevent="zoomChanging"/>
  <f:selectItems value="#{places.zoomLevelItems}"/>

  ...
</h:selectOneMenu>
...
<h:graphicImage id="progressbar" style="display: none"
              library="images" name="orange-barber-pole.gif"/>

Na Lista 13, inclua a imagem de uma barra de progresso, que inicialmente não é exibida, e especifique o atributo onevent para <f:ajax>. Esse atributo faz referência a uma função JavaScript, mostrada na Lista 14, que o JSF chama enquanto a chamada do Ajax iniciada na Lista 13 progride:

Lista 14. JavaScript que Responde a um Pedido do Ajax
function zoomChanging(data) {
  var menuId = data.source.id;
  var progressbarId = menuId.substring(0, menuId.length - "menu".length)
      + "progressbar";

  if (data.name == "begin") {
    Element.hide(menuId);
    Element.show(progressbarId);
  }
  else if (data.name == "success") {
    Element.show(menuId);
    Element.hide(progressbarId);
  }
}

O JSF passa à função na Lista 14 um objeto que contém algumas informações, como o identificador do cliente do componente que disparou o evento (neste caso, o menu de nível de zoom) e o status atual do pedido do Ajax, representado pela propriedade name denominada de forma indevida.

A função zoomChanging() mostrada na Lista 14 calcula o identificador do cliente da imagem da barra de progresso e, em seguida, usa o objeto Protótipo Element para ocultar e mostrar os elementos HTML apropriados durante a chamada do Ajax.


Conclusão

Ao longo dos anos, o JSF 1 desenvolveu uma reputação como uma estrutura que era difícil de usar. Em muitos aspectos, essa reputação era merecida. O JSF 1 foi desenvolvido em uma torre de marfim sem o retrospecto considerável que o uso no mundo real oferece. Como resultado, o JSF tornou muito mais difícil implementar aplicativos e componentes do que deveria ser.

O JSF 2, por outro lado, nasceu da experiência de um ensaio no mundo real, por pessoas que implementaram projetos de software livre sobre o JSF 1. Esse retrospecto do mundo real resultou em uma estrutura muito mais inteligente que facilita a implementação de aplicativos robustos com Ajax.

Ao longo desta série, mostrei alguns dos recursos mais proeminentes do JSF 2, como as anotações e convenção que substituem configuração, navegação simplificada, suporte para recursos, componentes compostos, Ajax integrado e o modelo de eventos expandido. Mas o JSF 2 possui muitos outros recursos que não cobri nesta série, como os escopos de Visualização e Página, suporte para páginas que podem ser marcadas e Estágio do Projeto. Todos esses recursos e outros mais tornam o JSF 2 um enorme aprimoramento de seu predecessor.


Download

DescriçãoNomeTamanho
Source code for the article examplesj-jsf2-fu-3.zip7.7MB

Recursos

Aprender

Obter produtos e tecnologias

  • JSF: Faça download do JSF 2.0.
  • GMaps4JSF: Faça download de GMaps4JSF

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=416059
ArticleTitle=JSF 2 fu, Parte 3: Manipulação de Eventos, JavaScript e Ajax
publish-date=07142009