Olá desenvolvedor! Se você vem do AngularJS 1 como eu, prepare-se!

As coisas mudaram muito por aqui!

Bom, ainda é javascript, ainda deixa o HTML poderoso e ainda é AngularJS, mas agora é tipado , componentizado e aparentemente mais organizado e rápido . Aparentemente, pois estou aqui apenas como um aventureiro e só vou ter certeza que é melhor quando fizer projetos inteiros, e não só rascunhos, para vislumbrar este mundo novo.

Com a versão 4 você elabora seus templates HTML, cria componentes para manipulá-los, coloca a lógica dos componentes nos serviços e empacota tudo isso em um módulo. Porém, esqueça aquela coisa de criar uma variável app e depois sair usando loucamente por aí, o papo agora é Typescript .

TypeScript é uma linguagem para desenvolvimento JavaScript em larga escala.

Com TypeScript podemos escrever código utilizando uma estrutura fortemente tipada e ter este código compilado para JavaScript puro.

Qualquer navegador. Qualquer host. Qualquer SO. Código Aberto.”

Pelo fato de ser tipado torna-se atraente para aqueles que são advindos de linguagens fortemente tipadas. Além disso, facilita demais o uso de ferramentas para tornar desenvolvedores mais produtivos.

 

Mas chega de papo: vamos à prática!


Hello World

Tudo tem que ter um começo, e só para manter o padrão, o AngularJS 4 tem o seu Hello World. Vamos a ele:

 
  git clone   https://github.com/angular/quickstart.git   quickstart

cd quickstart

npm install

npm start   

Pronto! É só isso. Sim! Eles usam NPM , não é incrível!? 

 

Hora de colocar a mão na massa!

Para ser bem prático, vou usar o Angular CLI  para criar meu projeto. Em seguida, vou reescrever uma demonstração  que fiz integrando com o Gravatar, de AngularJS 1 para AngularJS 4. Continue lendo, eu garanto que vai ser bem divertido :)

Vamos lá! Primeiro e mais óbvio, rodar o comando CLI

 
  npm install -g @angular/cli   

Depois criar um novo projeto

 
  ng new my-app   

*É importante que você tenha as últimas versões do NodeJS (6.9.X) e do NPM (3.X.X) antes de rodar esses comandos.

E agora, subir. Simples assim

 
  cd my-app

ng serve --open   

Acesse http://localhost:4200/ e temos um projeto pronto!

O restante do tutorial oficial do AngularJS 4, você pode encontrar aqui: https://angular.io/docs/ts/latest/cli-quickstart.html

 

Continuando...

Vamos reescrever uma demonstração que estava em AngularJS 1 para a versão 4 , então o jeito é deixá-lo com uma aparência melhor: mudar o título e adicionar uma descrição me parece algo bem atraente.

No componente que está em src/app/app.component.ts vamos alterar a propriedade title e criar uma outra chamada description:

 
  [...]
export class AppComponent {

 title = 'Gravatar';

 description = 'Uma demo feita em AngularJS 4';

}   

Ok, mas e como isso aparece no meu navegador? Simples, no arquivo src/app/app.component.html deixe o h1 assim:

 
  <h1>{{title}} <small>{{description}}</small></h1>   

Vai lá e atualize a página.. Oops, não precisa!! O AngularCLI já fez isso para você, que tal? 

Pra ficar mais bonito ainda, vamos carregar o Twitter Bootstrap . No arquivo src/index.html vamos colocar essa linhas dentro das tags head:

 
  <head>

[...]

 <link rel="stylesheet" href="https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css">

 <link rel="stylesheet" href="https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap-theme.min.css">

[...]

</head>   

Legal, agora lá no src/app/app.component.html deixe desta forma:

 
  <div class="container">
 <div class="page-header">
   <h1>{{title}} <small>{{description}}</small></h1>
 </div>

 <!-- aqui carregaremos o gravatar -->
</div>   

Até o momento só editamos arquivos existentes. Agora, vamos criar nosso primeiro componente, o gravatar. Para tanto, vamos criar uma nova pasta, a src/app/gravatar e nela criar três arquivos: gravatar.component.html , gravatar.component.ts e gravatar.service.ts .

Perceba que existe um padrão de nomenclatura a ser seguida:   recurso.tipo.extensão . Lembre-se disso, é crucial para manter tudo organizado e manutenível (leia mais sobre  clicando aqui ).

Quanto ao conteúdo dos arquivos, vamos começar por aquele que seria nosso controlador, o gravatar.component.ts :

 
  import { Component } from '@angular/core';


// importa o serviço como dependência
import { GravatarService } from './gravatar.service'


 @Component({

 selector: 'gravatar',

 templateUrl: './gravatar.component.html'

})

export class GravatarComponent {

 // Declarando propriedades

 email = ''

 resultado = null


 // Olha a tipagem ai..

 constructor(private service: GravatarService) { }


 // Metódo que será disparado pelo formulário do HTML, chamando um método do serviço

 onSubmit(): void {

   this.service.getProfile(this.email).then((resultado: JSON[]) => this.resultado = resultado);

 }

}   

Agora, continuamos com aquilo que seria a nossa view gravatar.component.html .

Repare na nova interpolação, eu ainda estou lutando pra entender e decorar como é cada coisa. Por via das dúvidas é melhor dar uma olhada na Documentação .

Se você já conhece o Angular, não vai ser lá um grande desafio, veja:

 
  <form (ngSubmit)="onSubmit()" #gravatarForm= ngForm">

 <div class="form-group">

   <input type="email" class="form-control" name="email" id="email" [(ngModel)]="email" placeholder="E-mail" #emailField= ngModel" required>

   <div *ngIf="emailField.errors && (emailField.dirty || emailField.touched)" class="alert alert-danger">

     <div [hidden]="!emailField.errors.required">

       E-mail é obrigatório

     </div>

   </div>

 </div>

 <button type="submit" class="btn btn-success form-control" [disabled]="!gravatarForm.form.valid">Obter dados do perfil</button>

</form>


<div *ngIf="resultado">

 <hr>

 <div class="panel panel-default">

   <div class="panel-heading">

     <h3 class="panel-title">Dados:</h3>

   </div>

   <div class="panel-body">

     <dl>

       <dt>Gravatar</dt>

       <dd>

         <img src="{{resultado.entry[0].thumbnailUrl}}" alt="emailGravatar" class="img-rounded">

       </dd>

     </dl>

     <dl>

       <dt>ID</dt>

       <dd>{{resultado.entry[0].id}}</dd>

     </dl>

     <dl>

       <dt>Nome</dt>

       <dd>{{resultado.entry[0].name.formatted}}</dd>

     </dl>

     <dl>

       <dt>URL</dt>

       <dd>{{resultado.entry[0].profileUrl}}</dd>

     </dl>

     <dl>

       <dt>Sobre</dt>

       <dd>{{resultado.entry[0].aboutMe}}</dd>

     </dl>

   </div>

 </div>

</div>


<pre *ngIf="resultado">

 {{resultado | json}}

</pre>   

E por fim, o nosso serviço gravatar.service.ts , aqui deve ficar toda a inteligência, o controlador serve apenas como ponte entre o serviço e a view:

 
  import { Injectable } from '@angular/core';

// Importando HTTP Jsonp já que o Gravatar não aceita HTTP Get

import { Jsonp } from '@angular/http';


// módulo de terceiros

// $ npm install ts-md5

import {Md5} from 'ts-md5/dist/md5'

// importando módulo para utilizar promisses (gostaria de tentar usar um callback normal, mas isso é uma outra publicação)

import 'rxjs/add/operator/toPromise';


 @Injectable()

export class GravatarService {

 // Olha a tipagem novamente

 constructor(private jsonp: Jsonp) {}

 

 // Metódo a ser chamado no controlador, fortemente tipado

 getProfile (email: string): Promise<JSON[]> {

   let hash = Md5.hashStr(email)

   

   // Requisição para o Gravatar

   return this.jsonp.get('//pt.gravatar.com/' + hash + '.json?callback=JSONP_CALLBACK')

       .toPromise()

       .then(response => response.json() as JSON[])

       .catch(this.handleError);

 }


 // Em caso de erro

 private handleError(error: any): Promise<any> {

   console.error('An error occurred', error); // for demo purposes only

   return Promise.reject(error.message || error);

 }

}   


Pra finalizar e tudo funcionar perfeitamente, é preciso alterar o src/app/app.module.ts a fim de declarar/carregar tudo que iremos utilizar em nossos componentes e carregar os próprios componentes.

Fica assim:

 
  import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

// Módulo para manipulação do formulário: model, validação, etc..
import { FormsModule } from '@angular/forms';

// Módulo HTTP, perceba que o Jsonp não vem por padrão neste módulo
import { HttpModule, JsonpModule } from '@angular/http';

import { AppComponent } from './app.component';


// Nosso módulo :)
import { GravatarComponent } from './gravatar/gravatar.component';
import { GravatarService } from './gravatar/gravatar.service'

 @NgModule({
 declarations: [
   AppComponent,
   GravatarComponent
 ],
 imports: [
   BrowserModule,
   FormsModule,
   HttpModule,
   JsonpModule
 ],
 providers: [GravatarService],
 bootstrap: [AppComponent]
})
export class AppModule { }   

Pronto, tudo deve funcionar agora!

Não deu? Comente nesta publicação ou baixe a demo pelo GitHub: 


Minhas impressões, finalmente!

Tive lá minha dificuldade com a sintaxe e onde cada código se encaixava. Mesmo assim, depois de pronto, fez muito sentido comparando com o AngularJS 1 . Algo que achei bem legal foram os plugins para os editores, no meu caso uso o Sublime Text 3 e o plugin de TypeScript e Angular 2, facilitou bastante o meu desenvolvimento, em resumo, o ‘ ctrl+espaço ’ funciona.  wink

Ainda existe um caminho longo, preciso estudar os testes, ir a fundo nas boas práticas, verificar a estabilidade para produto comercial. No geral achei bem bacana, e vou acompanhar o crescimento dessa versão.  

Acompanhe junto comigo aqui no Blog da TecnoSpeed! Em breve, teremos mais artigos como esse!