parametros - VWJavascript/Alurapic GitHub Wiki
Queremos reutilizar nosso componente para exibir diferentes imagens, mas sabemos que atualmente isso não é possível. O endereço da imagem está fixo no template do componente, o que não faz muito sentido.
Seria perfeito se pudermos passar o endereço da foto e o seu título desta maneira:
<!-- alurapic/client/app/app.component.html -->
<div class="jumbotron">
<h1 class="text-center">Alurapic</h1>
</div>
<div class="container">
<foto url="img/leao.jpg" titulo="Leão"></foto>
<foto url="img/leao-branco.jpg" titulo="Leão branco"></foto>
</div>
E podemos fazer isso sim, só precisamos preparar o nosso componente foto para receber os parâmetros titulo e url. Vamos alterar alurapic/client/app/foto/foto.component.ts e adicionar a propriedade que receberá os dados passados pelo usuário:
// alurapic/client/app/foto/foto.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'foto',
templateUrl: './foto.component.html'
})
export class FotoComponent {
titulo;
url;
}
Aqui temos uma peculiaridade do TypeScript. Em ES2015, só podemos definir as propriedades através do constructor, mas o TypeScript simplifica isso e podemos defini-las diretamente na classe. Contudo, isso não é suficiente.
Nem todas as propriedades de uma classe podem receber dados externos, é por isso que por padrão essas propriedades não recebem entrada. Para que seja possível passar valores para elas, precisamos usar o decorator Input, também importado do pacote @angular/core:
// alurapic/client/app/foto/foto.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'foto',
templateUrl: './foto.component.html'
})
export class FotoComponent {
@Input() titulo;
@Input() url;
}
Até aqui ditamos o que nosso componente está preparado para receber, porém em nenhum momento do seu template foto.component.html estamos usando essas informações. Primeiro, não temos mais o endereço da imagem nem seu título fixos:
<!-- alurapic/client/app/foto/foto.component.html -->
<img class="img-responsive center-block" src="" alt="">
E agora? Temos duas lacunas que precisam ser preenchidas em nosso template.
A ideia de templates com lacunas é semelhante aos documentos utilizados por advogados, por exemplo, para escreverem uma petição. Ele geralmente utiliza um modelo de documento com quase tudo pronto e altera apenas áreas que variam para todo caso em questão. Com isso, ele consegue poupar tempo e garantir um padrão.
Veja que o nosso componente recebe titulo e url, no entanto quem precisará ler essas informações é o seu template. Para que essa leitura seja possível, usamos uma sintaxe especial:
<!-- alurapic/client/app/foto/foto.component.html -->
<img class="img-responsive center-block" [src]="url" [alt]="titulo">
Veja que agora os atributos src e alt estão entre colchetes. Essa sintaxe particular realiza uma associação (binding) entre o atributo e sua respectiva fonte de dados. Sendo assim. o atributo src depende do dado url e o atributo alt do dado titulo. Em outras palavras, o que estamos realizando é uma associação de dados, o famoso data binding.
Angular possui mais de um tipo de data binding, mas por enquanto só precisamos saber que essa associação que fizemos é do tipo unidirecional, onde o dado caminha da fonte de dados para a view e nunca o caminho inverso. Qual a consequência disso? Nesse tipo de associação só lemos dados e nunca atualizamos.
Agora é só recarregarmos a nossa página e as duas imagens são exibidas através do nosso componente FotoComponent:
Veja que não houve manipulação de DOM para conseguirmos este resultado, um dos pontos fortes de frameworks que trabalham com data binding.
Ótimo! Tudo está funcionando, mas há uma sintaxe alternativa para o tipo de data binding que utilizamos, que é a Angular Expression (AE), muito utilizada na versão 1.0 do Angular!
Toda AE é caracterizada pelo uso de {{ }} e o que vier dentro das chaves duplas é o dado necessário para completar o template. Vamos alterar o template do nosso componente FotoComponent:
<!-- alurapic/client/app/foto/components/foto.html -->
<img class="img-responsive center-block" src="{{url}}" alt="{{titulo}}">
Tudo continua funcionando como antes, apesar de usarmos uma sintaxe alternativa para indicar o tipo de associação que fizemos antes.
Você deve ter reparado que tanto no componente AppComponent e no FotoComponent precisamos utilizar URL's absolutas para indicar a localização de seus templates na propriedade templateUrl. Contudo, isso não precisa ser assim. Vamos adicionar no decorator dos dois componentes a propriedade moduleId e passar o valor enigmático module.id. Com ele, podemos passar o caminho relativo dos templates:
// alurapic/client/app/app.component.ts
import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'app',
templateUrl: './app.component.html'
})
export class AppComponent { }
// alurapic/client/app/foto/foto.component.ts
import { Component, Input } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'foto',
templateUrl: './foto.component.html'
})
export class FotoComponent {
@Input() titulo;
@Input() url;
}
Veja que isso nos permite encontrar o template no próprio diretório do componente.