Templates

3

Porcentagem Traduzida

Neste capítulo, você irá:

  • Aprenda sobre a linguagem de templating do Meteor, a Handlebars.
  • Crie seus primeiros três templates.
  • Aprenda como os gerenciadores Meteor funcionam.
  • Tenha um protótipo básico funcionando com dados estáticos.
  • Para facilitar o desenvolvimento em Meteor, nós adotaremos uma abordagem de fora para dentro. Em outras palavras, nós iremos constuir uma casca externa “burra” com HTML/JavaScript primeiro, e então associar com o funcionamento interno de nosso aplicativo no subsequentes trabalhos.

    Isto significa que neste capítulo nós apenas nos preocuparemos com o que está acontecendo dentro do diretório /client.

    Vamos criar um novo arquivo chamado main.html dentro de nosso diretório /client, e vamos preenchê-lo com o seguinte código:

    <head>
      <title>Microscope</title>
    </head>
    <body>
      <div class="container">
        <header class="navbar">
          <div class="navbar-inner">
            <a class="brand" href="/">Microscope</a>
          </div>
        </header>
        <div id="main" class="row-fluid">
          {{> postsList}}
        </div>
      </div>
    </body>
    
    client/main.html

    Este será nosso principal template do aplicativo. Como você pode ver é HTML puro exceto por uma única tag {{> postsList}}“, a qual é um ponto de inserção para o template postList como logo veremos. Por enquanto, vamos criar mais alguns templates.

    Meteor Templates

    No seu âmago, um site de notícias sociais é composto de postagens organizadas em listas, e é exatamente assim que iremos organizar nossos templates.

    Vamos criar um diretório /views dentro de /client. Isto irá ser onde nós colocaremos nossos templates, e para manter as coisas organizadas nós também criaremos /posts dentro de /views apenas para nossos templates relacionados com postagens.

    Finding Files

    O Meteor é incrível para encontrar arquivos. Não importa onde você colocou o seu código no diretório /client, o Meteor irá encontrá-lo e compilá-lo corretamente. Isto significa que você nunca precisará manualmente escrever caminhos para inclusão de arquivos JavaScript ou CSS.

    Isto também significa que você poderia muito bem colocar todos os seus arquivos no mesmo diretório, ou ainda todo o seu código em um mesmo arquivo. Mas desde que o Meteor vai compilar tudo em um único arquivo minificado de qualquer forma, é melhor que mantemos as coisas bem organizadas e utilize uma estrutura clara de arquivos.

    Nós finalmente estamos prontos para nosso segundo template. Dentro de client/views/posts, crie posts_list.html:

    <template name="postsList">
      <div class="posts">
        {{#each posts}}
          {{> postItem}}
        {{/each}}
      </div>
    </template>
    
    client/views/posts/posts_list.html

    E post_item.html:

    <template name="postItem">
      <div class="post">
        <div class="post-content">
          <h3><a href="{{url}}">{{title}}</a><span>{{domain}}</span></h3>
        </div>
      </div>
    </template>
    
    client/views/posts/post_item.html

    Note o atributo name="postList" do elemento template. Este é o norme que será utilizado pelo Meteor para acompanhar qual template vai aonde.

    É hora de introduzir o sistema de templating do Meteor, o Handlebars. Handlebars é simplesmente HTML, com a adição de três coisas: parciais (partials), expressões (expressions) e blocos de ajuda (block helpers).

    As parciais usam a síntaxe {{> templateName}}, e simplemente dizem ao Meteor para substituir a parcial com o template de mesmo nome (no nosso caso postItem).

    Expressões tais como {{title}} ou chamam a propriedade do objeto atual, ou retornam o valor de um auxiliar do template como definido no gerenciador atual do template (logo mais sobre isso).

    Finalmente, blocos de ajuda são tags especiais que controlam o fluxo do template tais como {{#each}}...{{\each}} ou {{#if}}...{{\if}}.

    Indo Além

    Você pode visitar o site oficial de Handlebars ou este prático tutorial se quiser aprender mais sobre Handlebars.

    Armado com este conhecimento, nós podemos facilmente entender o que está acontecendo aqui.

    Primeiro, no template postsList, nós estamos iterando sobre um objeto posts com o bloco de ajuda {{#each}}...{{\each}}. Então, para cada iteração nós incluimos o template postItem.

    De onde este objeto posts se origina? Boa pergunta. Se trata na verdade de um ajudante do template, e nós iremos defini-lo quando olharmos para os gerenciadores de template.

    O template postItem em si mesmo é bem direto. Apenas usa três expressões: {{url}} e {{title}} ambas retornando as propriedades do documento, e {{domain}} que chama um ajudante do template.

    Nós mencionamos "ajudantes do template” bastante ao longo deste capítulo sem realmente explicar o que eles fazem. Mas para consertar isso, primeiro precisamos falar sobre gerentes.

    Gerentes de Template

    Até agora nós estávamos lidando com Handlebars, que nada mais é do que HTML acrescido de algumas tags especiais. Diferentemente de outras linguagens de programação como o PHP (ou até mesmo páginas HTML comuns, que podem incluir JavaScript), o Meteor mantém os templates e as lógicas separadas e esses templates não fazem muita coisa por si só.

    Para fazer com que eles ganhem vida é necessário um gerente. Você pode pensar em um gerente como um chef de cozinha que pega os ingredientes crus (seus dados) e prepara eles antes de entregar o prato finalizado ao garçom (o template) que o apresenta a você.

    Em outras palavras, enquanto o papel do template se limita a exibir ou iterar variáveis, o gerente é aquele que faz todo o trabalho pesado atribuindo valores para cada uma dessas variáveis.

    Gerentes?

    Quando nós perguntarmos por aí a outros desenvolvedores Meteor como eles chamam esses “gerentes de template”, metade respondeu “controllers” e a outra metade respondeu “aqueles arquivos onde eu coloco meu código JavaScript”.

    Gerentes não são de fato “controllers” (pelo menos não no sentido de controllers do MVC) e como a sigla “AAOECMCJ” (Aqueles Arquivos Onde Eu Coloco Meu Código Javascript) não é muito atraente, nós acabamos rejeitando as duas opções.

    Como ainda precisávamos usar um nome para indicar aquilo a que estávamos nos referindo, nós optamos pelo termo “gerente” como uma alternativa viável já que não tinha um significado relacionado a nenhum outro framework web.

    Para simplifcar as coisas, nós iremos adotar a mesma convenção de nomes utilizada para o template, com exceção da utilização da extensão .js. Vamos criar o arquivo posts_list.js dentro do diretório /client/views/posts e começar a definir nosso primeiro gerente:

    var postsData = [
      {
        title: 'Introducing Telescope',
        author: 'Sacha Greif',
        url: 'http://sachagreif.com/introducing-telescope/'
      }, 
      {
        title: 'Meteor',
        author: 'Tom Coleman',
        url: 'http://meteor.com'
      }, 
      {
        title: 'The Meteor Book',
        author: 'Tom Coleman',
        url: 'http://themeteorbook.com'
      }
    ];
    Template.postsList.helpers({
      posts: postsData
    });
    
    client/views/posts/posts_list.js

    Se você fez tudo certo, algo parecido com isso irá aparecer no seu navegador:

    Nosso primeiro template com dados estáticos
    Nosso primeiro template com dados estáticos

    Commit 3-1

    Template de listagem de posts e dados estáticos adicionados.

    Nós estamos fazendo duas coisas aqui. Primeiro estamos colocando alguns dados de teste no array postsData. Esses dados normalmente seriam provenientes de um banco de dados, mas como ainda não vimos como acessá-lo (aguarde até o próximo capítulo) nós estamos “trapaceando” usando alguns dados estáticos. Depois estamos usando a função Template.myTemplate.helpers() do Meteor para definir um ajudante de template chamado posts que simplesmente nos retornará o array postsData.

    Definir o ajudante posts significa que ele agora estará disponível para ser usado pelo nosso template:

    <template name="postsList">
      <div class="posts">
        {{#each posts}}
          {{> postItem}}
        {{/each}}
      </div>
    </template>
    
    client/views/posts/posts_list.html

    Agora será possível que nosso template itere sobre o array postsData e envie cada objeto contido dentro dele para o template postItem.

    O valor do “this”

    Nós iremos criar agora o gerente post_item.js

    Template.postItem.helpers({
      domain: function() {
        var a = document.createElement('a');
        a.href = this.url;
        return a.hostname;
      }
    });
    
    client/views/posts/post_item.js

    Commit 3-2

    Definição do ajudante `domain` no template `postItem`.

    Desse vez o valor do ajudante domain não é um array, mas uma função anônima. Esse pattern é muito mais comum (e mais útil) se comparado aos nossos exemplos com dados de teste anteriores.

    Exibindo os domínios de cada link.
    Exibindo os domínios de cada link.

    O ajudante domain recebe uma URL e retorna seu domínio utilizando um pouco da mágica do Javascript. Mas, pra começar, de onde ela pega essa URL?

    Para responder a essa pergunta nós precisamos voltar ao nosso template posts_list.html. O ajudante {{#each}} não apenas itera um array mas também atribui o valor do this dentro do bloco do objeto iterado.

    Isso significa que entre as duas tags {{#each}}, cada post é atribuído ao this sucessivamente e isso também se aplica ao gerente de template (post_item.js).

    Agora nós entendemos o porque do this.url retornar a URL do post atual. E além disso, se nós usarmos {{title}} e {{url}} dentro do nosso template post_item.html, o Meteor sabe que isso significa this.title e this.url e retorna os valores corretos.

    Mágica do Javascript

    Embora isso não seja especifíco do Meteor, aqui vai uma breve explicação a respeito dessa pequena “mágica do Javascript” descrita acima. Primeiro, nós estamos criando um elemento HTML de âncora (a) vazio e armazenando-o na memória.

    Depois colocamos em seu atributo href a URL do post atual (como nós já vimos, o this corresponde ao objeto sob a qual a ação está acontecendo).

    Por último, nós aproveitamos o fato de que o elemento a tem uma a propriedade especial chamada hostname para recuperar o nome de domínio do link sem o restante da URL.

    Se você seguiu tudo corretamente, deverá estar vendo agora uma lista de posts no seu navegador. Essa lista é composta apenas por dados estáticos, portanto ela ainda não tira vantagem dos recursos real-time do Meteor. Nós iremos mostrar como mudar isso no próximo capítulo!

    Recarregamento Automático de Código

    Você deve ter notado que não precisa nem recarregar a janela do seu navegador quando altera um arquivo.

    Isso acontece porque o Meteor rastreia todos os arquivos dentro do diretório do seu projeto e automaticamente dá refresh no seu navegador sempre que detecta mudanças em algum desses arquivos.

    O recarregamento automático de código do Meteor é bem esperto! Ele até preserva o estado da sua aplicação entre um refresh e outro!