Neste codelab,você criará um formulario de checkout que utiliza a API autofill para ajudar os usuários a rapidamente e com precisão completar suas compras. No processo você aprenderá como usar os Gold Elements do Polymer, layout classes, e as noções básicas para trabalhar com o elemento iron-form.

O que você aprenderá

O que você precisará

Como você classificaria sua experiência com Polymer?

Novato Intermediario Avançado

Criando um novo projeto

Na primeira execução do Chrome Dev Editor você precisará configurar o seu workspace..

Inicie o Chrome Dev Editor e crie um novo projeto:

  1. Clique em para criar um novo projeto.
  2. Digite "PolymerCheckoutForm" em Project name.
  3. Em Project type, selecione "JavaScript web app (usando o elemento Polymer paper)".
  4. Clique no botão Create.

O Chrome Dev Editor criará um template basico para seu aplicativo Polymer. Em segundo plano, usará o Bower para fazer download e instalar as dependências (incluindo as bibliotecas do core do Polymer) na pasta bower_components/ . A instalação desses componentes pode demorar se sua conexão com a Internet estiver lenta.

Estrutura do Projeto

PolymerCheckoutForm/
  bower_components/ <!-- installed dependencies from Bower -->
  bower.json  <!-- Bower metadata files used for managing deps -->
  index.html  <!-- your app -->
  main.js
  styles.css

Pre-visualizando o app

Em qualquer momento, selecione o arquivo index.html e clique no botão na toolbar para executar o app. O Chrome Dev Editor inicializará um servidor web e abrirá a página index.html. Esta é uma ótima maneira de visualizar as alterações que você fizer.

Próximo

Nesse ponto o app não faz muita coisa. Vamos iniciar criando um container para receber nosso formulário.

O elemento <paper-material> é um container genérico que se assemelha a uma folha de papel elevada.

Instalando o conjunto de elementos

Normalmente, você digitaria bower install polymerelements/paper-material --save na linha de comando para instalar o <paper-material> e salvar suas dependências, porém o Chrome Dev Editor não possui linha de comando para executar os comandos do Bower. Em vez disso, você precisa editar manualmente o arquivo bower.json para incluir os elementos que você precisa, então execute a opção Bower Update do Chrome Dev Editor. Bower Update verifica as dependências no arquivo bower.json e instala as que estiverem faltando.

Esse tutorial exige os conjuntos de elementos paper, iron, e gold do Polymer, por isso você precisa adicioná-los em seu arquivo bower.json.

  1. Altere o arquivo bower.json e adicione os elementos paper, iron e gold no objeto dependencies:
"dependencies": {
  "paper-elements": "polymerelements/paper-elements#^1.0.4",
  "iron-elements": "polymerelements/iron-elements#^1.0.3",
  "gold-elements": "polymerelements/gold-elements#^1.0.1"
}
  1. No editor, click com o botão direito no arquivo bower.json.
  2. Selecione a opção Bower Update.

O download pode demorar alguns segundos. Você pode verificar que o elemento <paper-material> (e todas dependências) foi adicionado checando se o diretório bower_components/paper-material/ foi criado e os arquivos estão presentes.

Usando o elemento <paper-material>

Para usar o elemento <paper-material>, você precisa:

  1. Usar o HTML Import para carregar o elemento no index.html.
  2. Declarar uma instância do elemento na página.

O projeto padrão do Chrome Dev Editor tem muito mais do que você precisa para este tutorial, então substitua todo conteúdo do arquivo index.html pelo código abaixo:

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">

    <title>Polymer Checkout Form</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Web Components -->
    <script src="bower_components/webcomponentsjs/webcomponents-lite.min.js">
    </script>
    <!-- Imports will go here -->
    <link rel="stylesheet" href="styles.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto">
  </head>
  <body unresolved>

  </body>
</html>

Encontre a linha que contém <!-- Imports will go here --> e substitua com o seguinte código:

<link rel="import" href="bower_components/paper-material/paper-material.html">

Agora que a importação já foi adicionada você pode usar o seu elemento. Atualize o conteúdo da tag <body> com uma instância do elemento <paper-material>:

index.html

<body unresolved>
  <paper-material class="card" elevation="1">
    Hello World!
  </paper-material>
</body>

Há algumas coisas interessantes acontecendo aqui. Você deve ter notado o atributo unresolved na tag <body> e pode estar se perguntando para que serve esse atributo? Em navegadores que suportam Web Components, a renderização da página é bloqueada até que todas as definições dos componentes sejam carregadas (a menos que você adicione um atributo async em suas importações).

Isto é para evitar o "Flash of Unstyled Content", ou FOUC. Coincidentemente, CSS também funciona dessa forma—você notou que ambas as importações de HTML e CSS usam a tag <link>? Esta é uma excelente funcionalidade dos Web Components, mas porque nem todos os navegadores suportam totalmente os padrões ainda, precisamos usar um polyfill para esse comportamento, e isso é exatamente o que o unresolved faz. Ele esconde o conteúdo da página até que todas as suas importações tenham sido carregadas, e só então revela o conteúdo final!

Confira o elemento <paper-material> e você verá que ele tem uma classe para o estilo (que você usará em alguns instantes), bem como um atributo chamado elevation, que define o quão profunda a sombra será visualizada na página. Um dos melhores aspectos de trabalhar com custom elements é que eles são facilmente configurados na marcação. Em um momento você visualizará o aplicativo e quando o fizer, não se esqueça de mudar esse atributo. Defina o atributo elevation como 0 ou 5, ou algum número inteiro entre 0 e 5 e veja as alterações.

Aplicando estilos!

Abra o arquivo styles.css e substitua seu conteúdo com os estilos logo abaixo:

styles.css

body {
  font-family: 'Roboto', 'Noto', sans-serif;
  font-size: 14px;
  margin: 0;
  padding: 24px;
  background-color: #FAFAFA;
}

.card {
  background: #FFFFFF;
  max-width: 400px;
  padding: 24px;
  margin: 0 auto;
}

Esta configuração define a tipografia e proporciona ao elemento <paper-material> (que tem a classe card) algumas dimensões básicas.

Execute o app

Se você ainda não o fez, aperte o botão . Neste ponto, você deve ver um bloco com o texto Hello World! dentro dele.

Próximo passo

É um começo, mas ainda há muito o que fazer! Na próxima etapa, você construirá o formulário e testará seu autopreenchimento.

Para tornar o formulário verdadeiramente reutilizável, você pode criar um custom element que contém sua definição.

  1. Clique com o botão direito na barra lateral do projeto PolymerCheckoutForm
  2. Selecione New File (Novo Arquivo)
  3. Nomeie o novo arquivo de checkout-form.html e clique em Create (Criar)

No check-out-form.html, atualize o HTML para que ele se pareça com o código abaixo :

checkout-form.html

<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="bower_components/iron-flex-layout/classes/iron-flex-layout.html">

<dom-module id="checkout-form">

  <template>
    <style></style>
  </template>

  <script>
    Polymer({

      is: 'checkout-form'

    });
  </script>

</dom-module>

Este é um formato padrão para criação de um novo elemento Polymer. No topo você está importando dependências para garantir que elas são carregadas antes do seu elemento tentar interagir com eles.

A seguir temos o <dom-module>, o qual tem como id o checkout-form. O <template> contido no <dom-module> é onde você colocará toda marcação para o seu elemento. Sempre que alguém usar uma instância do <checkout-form>, esta é a marcação que será visualizada na página. Você pode estilizar essa marcação usando uma tag <style>.

Finalmente temos uma tag <script> na qual você invoca o construtor Polymer passando um objeto que define o protótipo para seu elemento. Notou como a propriedade is no protótipo corresponder ao id do <dom-module>? É assim que os dois podem se encontrar mais tarde, quando você finalmente concatenar e minificar todos os elementos em um grande pacote para a produção.

Uma especial linha é esta aqui:

<link rel="import" href="bower_components/iron-flex-layout/classes/iron-flex-layout.html">

A importação do elemento iron-flex-layout contém estilos úteis para trabalhar com flexbox. Se você nunca trabalhou com Flexbox antes, prepare-se para mudar sua vida completamente! Flexbox torna o processo de criar layouts CSS muito mais gerenciável. Uma vez que você aprender a usá-lo você nunca mais olhará para trás. Normalmente, trabalhando com flexbox requer um número de prefixos CSS e propriedades com nomes estranhos, mas a folha de estilo fornecida pelo iron-flex-layout suaviza todo esse trabalho.

Dê personalidade ao seu formulário

Vamos usar o Flexbox para colocar um cabeçalho no formulário. Atualize o <template> com o seguinte conteúdo.

checkout-form.html

<template>
  <style></style>
  <div class="horizontal layout center form-title">
    <div class="avatar" item-icon></div>
    <div class="flex company">ACME Goods Co.</div>
  </div>
</template>

Observe as classes horizontal, layout e center no primeiro <div>? Essas são classes flexbox do iron-flex-layout. Eles traduzem para os seguintes estilos: "Usando flexbox, aplique o layout dos elementos filhos horizontalmente e verticalmente alinhe seus pontos centrais". Da mesma forma, a classe flex no último filho se traduz em: "Preencha o máximo que for possível do container pai." Note que também existe uma classe form-title no <div>. Essa é uma classe personalizada que você utilizará mais tarde.

O próximo passo é atualizar os estilos para estes <div> s para que eles realmente se pareçam com a marca da sua empresa fictícia.

<style>
  :host {
    display: block;
  }

  .form-title {
    margin-bottom: 20px;
  }

  .avatar {
    display: inline-block;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    overflow: hidden;
    background: #3367d6;
    margin-right: 20px;
  }

  .company {
    color: #3367d6;
    font-size: 20px;
    font-weight: 200;
  }
</style>

Não há nada demais nos estilos vistos acima com a excepção do seletor :host. Quando um elemento necessita referir-se a si mesmo você pode fazê-lo com o :host. Neste caso, o elemento está dizendo que ele deve ser exibido como elemento de bloco display: block. Por padrão, todos os elementos personalizados são exibidos como elemento em linha display: inline.

Adicionando o formulário em sua página

No elemento <head> do index.html, depois de importar o paper-material.html adicione outro html import para o checkout-form.html

index.html

<link rel="import" href="bower_components/paper-material/paper-material.html">
<link rel="import" href="checkout-form.html">

Finalmente, adicione uma instância da tag <checkout-form> em seu elemento <paper-material>.

<body unresolved>
  <paper-material class="card" elevation="1">
    <checkout-form></checkout-form>
  </paper-material>
</body>

Execute o app

Aperte o botão ! Neste ponto, você verá um formulário com a marca da nossa empresa fictícia no topo. Observou como os <div>s estão dispostos horizontalmente e têm os seus centros alinhados? Isso é o flexbox em ação!

Próximo passo

Aprender a utilizar os elementos Iron, Paper e Gold para auto-preencher o formulário.

Para finalizar o visual do formulário, você precisará usar os elementos Iron, Paper e Gold.

No check-out-form.html adicione novas importações HTML para esses componentes no início do arquivo depois das outras importações.

checkout-form.html

<link rel="import" href="bower_components/iron-form/iron-form.html">
<link rel="import" href="bower_components/paper-input/paper-input.html">
<link rel="import" href="bower_components/paper-button/paper-button.html">
<link rel="import" href="bower_components/gold-cc-input/gold-cc-input.html">
<link rel="import" href="bower_components/gold-email-input/gold-email-input.html">
<link rel="import" href="bower_components/gold-cc-cvc-input/gold-cc-cvc-input.html">
<link rel="import" href="bower_components/gold-cc-expiration-input/gold-cc-expiration-input.html">

Combinando o iron-form com elementos input customizados

Adicione o seguinte HTML dentro da tag <template> no arquivo checkout-form.html, logo após do logotipo da nossa empresa fictícia.

checkout-form.html

<form is="iron-form" id="form" method="post" action="/checkout">
  <paper-input name="name" label="Name on card" required autocomplete="cc-name"></paper-input>
</form>

Se você colocar um elemento personalizado dentro de uma tag <form> nativa, isto não funcionará. A tag <form> nativa apenas provê suporte a um subconjunto de elementos. Digite <iron-form>. O elemento <iron-form> se comporta de forma semelhante à tag nativa <form>, mas permite enviar conteúdo para qualquer elemento filho que implementa o Polymer.IronFormElementBehavior.

Observe que o elemento iron-form estende a tag nativa form. Isso é para que possamos pegar carona no comportamento de coleta de valores para elementos nativos, enquanto adicionamos um comportamento adicional para trabalhar com elementos input personalizados. O formulário define através dos atributos method e action como suas solicitações devem ser enviadas. Note que estes são atributos padrão herdados da tag <form> nativa. Para esta demonstração não iremos interagir com backend, mas agora você sabe como usá-los em seus aplicativos futuros.

Dê uma olhada nos atributos do elemento <paper-input>. name é o nome do campo que será apresentado como parte do conteúdo do formulário. label é uma linha de texto que irá funcionar como um placeholder até que o usuário comece a digitar; uma vez que o usuário tenha começado a digitar esta etiqueta irá flutuar acima do que já foi digitado para manter o contexto.

required indica que o formulário não pode ser submetido a menos que este campo seja preenchido. Por último, autocomplete especifica qual parte da autofill API este campo deve ser ligado. O valor cc-name informa para a API solicitar ao usuário o nome em seu cartão de crédito se essa informação já está disponibilizada em seu navegador.

Se você voltar para o index.html e pressionar o botão você verá que o <paper-input> está funcionando praticamente como esperado, mas não estamos vendo qualquer comportamento de auto-preenchimento ainda e isso é porque ainda precisamos adicionar mais alguns campos.

Em vez de usar elementos paper-input para os campos de cartão de crédito restantes, vamos passar a usar elementos gold-*. Os Gold Elements funcionam como campos <paper-input>, mas também incluem suporte para validação, etiquetas padrão e já contêm os atributos de preenchimento automático adequados.

Adicione o seguinte código no arquivo checkout-form.html depois do <paper-input> para o cc-name.

checkout-form.html

<form is="iron-form" id="form" method="post" action="/checkout">

  ...

  <gold-cc-input name="cc-number" required auto-validate card-type="{{typeOfCard}}"></gold-cc-input>

</form>

O campo <gold-cc-input> solicitará ao usuário o número de seu cartão e porque ele contém um atributo auto-validate também verificará se o número do cartão é válido. Depois de ter verificado que o cartão é válido, ele irá atualizar sua propriedade cardType para indicar que tipo de cartão foi introduzido (Visa, American Express, etc). Você pode fazer um bind a este valor com o atributo card-type.

Ao criar uma variável de escopo, typeOfCard, que está vinculada ao valor de cardType, você pode dizer aos outros elementos que tipo de cartão eles devem tentar validar (e você pode exibir uma imagem do cartão, como você verá logo a seguir).

As duas últimas partes de dados que você precisará são a data de validade e o Código de Verificação do Cartão (muitas vezes referenciado como CVC ou CVV). Vamos usar mais alguns elementos Gold para esses campos.

checkout-form.html

<form is="iron-form" id="form" method="post" action="/checkout">

  ...
  
  <div class="horizontal layout">
    <gold-cc-expiration-input name="cc-expiration" required auto-validate label="Expiration"></gold-cc-expiration-input>
    <gold-cc-cvc-input name="cc-cvc" required auto-validate card-type="[[typeOfCard]]"></gold-cc-cvc-input>
  </div>

</form>

Como os campos são curtos, você pode ter os dois na mesma linha os envolvendo em um <div> e usando os atributos de layout para fazer outro layout horizontal (similar a marca da empresa fictícia de mais cedo).

Note também que o elemento <gold-cc-cvc-input> tem uma ligação para o card-type. Como estamos usando colchetes isso significa que este é um one way binding, de modo que este elemento só pode receber dados. Neste caso, tão logo o elemento <gold-cc-input> sabe o tipo de cartão informado pelo usuário, ele envia essa informação para o <gold-cc-cvc-input>. Como diferentes tipos de cartão têm diferentes valores CVC (Visa usa 3 dígitos e a American Express utiliza 4 dígitos), esta informação ajuda o <gold-cc-cvc-input> na validação do cartão.

A última coisa a fazer é adicionar um pouco de estilo para que o prazo de validade fique na mesma linha do CVC. Adicione este código ao final da tag <style>.

checkout-form.html

gold-cc-expiration-input {
  width: 50%;
  margin-right: 20px;
}

Execute o app

Mude para o index.html e click no botão ! Você verá um formulário utilizando toda a beleza do Material Design. Se você tentar preenchê-lo, você receberá um alerta dizendo que o preenchimento do cartão de crédito foi desabilitado porque você não está em uma conexão segura (em outras palavras, seu formulário não está sendo servido via https).

Isso é ótimo porque demonstra que a autofill API está tentando tirar proveito dos nossos elementos, mas ainda não é o que esperamos, pois ainda não podemos testar a forma real. Não se preocupe, nós podemos terminar de arrumar as coisas e, em seguida, fazer um teste final em um servidor real.

Próximo passo

Adicionando um botão de pagamento para submeter o formulário.

O que é um formulário de check-out se o usuário não pode realmente enviá-lo? Nesta última seção, você vai adicionar um botão de pagamento que finaliza o checkout e faz com que você (hipoteticamente) se torne rico!

No arquivo checkout-form.html adicione um <paper-button> com o seguinte markup:

checkout-form.html

<form is="iron-form" id="form" method="post" action="/checkout">
  ... <!-- Our form fields -->

  <paper-button on-click="_submit">Pay</paper-button>
</form>

O Polymer facilita a criação de event handlers usando a sintaxe on-*. O Polymer irá lidar com a configuração dos listeners quando seu elemento é adicionado ao DOM, e o mais importante, removê-los quando o elemento for removido do DOM. Isso ajuda a evitar possíveis memory leaks (vazamentos de memória)!

Você precisa fornecer um método _submit que será executado em resposta ao evento.

checkout-form.html

<script>
  Polymer({

    is: 'checkout-form',

    _submit: function() {
      this.$.form.submit();
    }

  });
</script>

O método _submit é prefixado com um sublinhado para significar para o mundo exterior que ele é um método privado. Dentro do método, chame this.$.form.submit(). Chamando o this.$.form ele retornará uma referência para o elemento iron-form usando a funcionalidade de Automatic Node Finding (mais detalhes abaixo) do Polymer instruindo o formulário para enviar via AJAX.

Adicione um pouco de CSS para que o botão preencha completamente a parte de baixo do formulário. Você pode adicionar este código no final da tag <style> dentro do check-out-form.html

checkout-form.html

paper-button {
  background-color: #4285f4;
  color: #fff;
  margin-top: 50px;
  width: 100%;
}

Não temos um backend real para o processamento de cartões de crédito (e provavelmente não seria uma coisa muito segura para tentar definir durante um codelab!) vamos adicionar um listener ao evento de submit do formulário e apenas armazenar o log no console .

Ao invés de escrever um outro event handler na marcação, vamos usar o Polymer listeners object. Semelhante ao automatic node finding, os objetos listeners encontrarão qualquer elemento com um id para que você possa usá-lo para ouvir diretamente do elemento iron-form. Atualize o protótipo do seu elemento com o seguinte código:

checkout-form.html

Polymer({

  is: 'checkout-form',

  listeners: {
    'form.iron-form-submit': '_handleFormSubmit'
  },

  _submit: function() {
    this.$.form.submit();
  },

  _handleFormSubmit: function() {
    console.log('Form submitted successfully! You are so rich now!');
  }

});

Experimente a versão final

Você pode voltar para o index.html e apertar o botão para ver uma versão local de seu formulário em execução. Como da última vez, você não será capaz de preencher automaticamente o formulário, mas você pode digitar os valores manualmente e pressionar o botão enviar para ver a mensagem de sucesso registrada no console. Como não existe nenhum tratamento para a url /checkout, um erro será retornado. Em um aplicativo real, no entanto, você pode enviar uma resposta para que o usuário saiba se o seu pagamento foi aceito ou não.

Para testar o recurso de preenchimento automático, dê uma olhada nesta versão do formulário utilizando https com o Firebase. Nenhuma informação será armazenada ou enviada para algum lugar, por isso, se acontecer do formulário ser preenchido automaticamente com os dados de um cartão de crédito verdadeiro não se preocupe.

Se você já tiver guardado o seu cartão de crédito no Chrome, este lhe solicitará para completar automaticamente assim que você começar a digitar seu nome. Se tudo correr bem, você deve ver algo parecido com o screenshot abaixo (cartão de crédito falso fornecido).

Dependendo de como você tiver armazenado as informações do seu cartão, o número CVC pode ou não ser preenchido automaticamente.

Então, você conseguiu! Um formulário de check-out no qual você pode aplicar sua própria marca. Um estudo recente conduzido pelo Google mostra que quando os formulários são preenchidos automaticamente com informações já salvas, os usuários tendem a completá-los cerca de 30% mais rápido!

Agorá você já consegue fazer algum dinheiro com a ajuda do Polymer e suas novas habilidades!

O que você aprendeu

Aprenda mais

Polymer

Forms