Essencial
Nos velhos tempos, desenvolver para a web, envolvia aplicativos do lado cliente altamente acoplados à infraestrutura do servidor. Muito hardware estava envolvido para que uma simples página HTML solicitada via URL a um servidor pudesse aparecer em seu navegador. Isso quando tudo dava certo, por que a chance de algo dar errado ou mesmo atrasar, era enorme.
Aplicações modernas eliminam estes erros através da arquitetura SPA, por exemplo. Um único arquivo HTML é solicitado ao servidor pelo cliente. Quaisquer alterações subsequentes na URL do navegador são tratadas internamente pelo lado do cliente. No Angular, o responsável por interceptar solicitações de URL no aplicativo e manuseá-las de acordo com as rotas definidas chama-se router/roteador.
O projeto
Neste primeiro projeto, vamos criar um blog pessoal, uma transição suave do que já dominamos – HTML e CSS, certo!? – para SPA/Angular. Para tanto vamos utilizar Jamstack e Scully. Inicialmente vamos o scallfold do Angular para uma nova aplicação com rotas ativadas. Vamos criar um layout básico para nossa aplicação e adicionar alguns componentes. Em seguida, quando tivermos uma aplicação Angular funcionando, adicionaremos suporte ao blog através do Scully. Depois é só adicionar alguns posts e mostra-los na home page.
Início
ng new meu-blog --routing --style=scss
Caso seja necessário, atualize a versão da Jasmine em package.json para:
"jasmine-core": "~3.8.0",
Em seguida, não esqueça de npm i
Quando habilitamos o roteamento em uma aplicação Angular, o Angular CLI importa pacotes NPM @angular/router
para nossa aplicação.
É criado o arquivo app-routing.module.ts com a rota principal da aplicação:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
É importado AppRoutingModule para dentro do modulo principal de nossa aplicação, app.module.ts:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Nós configuramos nossa aplicação para usar SCSS no estilo. Ao invés de criar nossos estilos manualmente, vamos pedir ajuda a biblioteca Bootstrap CSS.
npm i bootstrap
Uma vez que o pacote foi instalado, adicionamos o import
no topo do arquivo styles.scss
:
@import "~bootstrap/scss/bootstrap";
O arquivo styles.scss
contém os estilos globais aplicados sobre a aplicação. Utilizamos ~para representar o diretório node_modules
. Lembre-se de verificar o endereço.
Básico do layout
Tipicamente um Blog contém um cabeçalho com todos os links(de primeira ordem) do website e um rodapé com os direitos autorais e outros links úteis. No mundo do Angular, ambos podem ser representados por componentes diferentes.
O componente Cabeçalho será usado apenas uma vez, no inicio da aplicação, e sempre será renderizado como o menu principal do site.
No Angular, normalmente é criado um módulo que sustenta componentes e serviços centrais da nossa aplicação, por convenção, chamado core.
ng generate module core
Processado o comando, a pasta \core
terá sido criado dentro da pasta \app
. Agora criamos o componente cabeçalho, com o mesmo comando, porém com mais opções:
Header
ng g c header --path=src/app/core --module=core --export
O comando irá criar todos os arquivos necessários dentro da pasta \app\core\header
.
Observe agora como ficou o arquivo do módulo Core. Observe as linhas 3, 7 e 12.
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HeaderComponent } from './header/header.component';
@NgModule({
declarations: [
HeaderComponent
],
imports: [
CommonModule
],
exports: [
HeaderComponent
]
})
export class CoreModule { }
O cabeçalho pode mostrar os links principais do nosso blog. Abra o template do componente, header.component.html
e substitua o código por um componente de navegação Bootstrap.
<nav class="navbar navbar-expand bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
</ul>
</div>
</nav>
Footer
O componente do rodapé pode ser usado mais de uma vez em uma aplicação Angular. Atualmente, queremos exibi-lo na página principal do nosso aplicativo. No futuro, podemos querer tê-lo também em uma página de login que estará disponível para os visitantes do blog. Nesse caso, o componente do rodapé deve ser reutilizável. Quando queremos agrupar componentes que serão reutilizados ao longo de nossa aplicação, normalmente criamos um módulo chamado shared
, por convenção.
ng g m shared
ng g c footer --path=src/app/shared --module=shared --export
Mais uma vez, criamos o módulo shared, em seguida o componente footer dentro dele. Pegou o jeito neah? Dá uma espiada no shared.module.ts
e confira se o componente foi devidamente importado para dentro dele.
Como mencionamos, o conteúdo do rodapé contém informações autorais sobre nosso Blog. Vamos adiciona-los ao componente então. Abra o arquivo footer.component.ts
, localize a classe FooterComponent
e nesta, adicione a propriedade dataAtual
.
...
export class FooterComponent implements OnInit {
dataAtual = new Date();
constructor() { }
ngOnInit(): void {
}
}
Agora alteramos o template para receber o conteúdo. Ao processar o código do componente, ocorrerá a interpolação da propriedade, mostrando o valor na tela.
<nav class="navbar fixed-bottom navbar-light bg-light">
<div class="container-fluid">
<p>Copyright @{{ dataAtual | date: "y" }}. All Rights Reserved</p>
</div>
</nav>
Neste caso, além da interpolação, que ocorre através da notação mustache/bigode {{ }}
, temos um Pipe, para mostrar apenas o ano. Pipes são funções incorporadas na estrutura do Angular, built-ins, que aplicam transformações na visualização de propriedades em componentes. O valor da propriedade permanece intacto, é apenas um cosmético 🎨.
Criamos os componentes essenciais. Ufa! Bora mostrar!?
- Primeiro, abra o módulo principal da aplicação –
app.module.ts
– e faça a importação dos módulos –CoreModule
eSharedModule
– emimports
. - Depois, acrescente as sentenças de importação, no topo do arquivo. Os erros sumiram?
- Agora, podemos usar as novas tags/seletores para substituir o conteúdo do arquivo
app.component.html
:: Atenção :: O ciclo acima se repetira diversas vezes, tenha certeza de ter entendido o que realmente esta acontecendo e os motivos, caso tenha dúvidas, leia o tópico Essencial.
import { SharedModule } from './shared/shared.module';
import { CoreModule } from './core/core.module';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
CoreModule,
SharedModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
<app-header></app-header>
<app-footer></app-footer>
Layout pronto! Uffa! Muito, por quase nada. Eu sei, mas há muitos benefícios nesta pesada estrutura. Colocamos dois links que não levam a lugar algum. Partiu, rotas!
Rotas
Aguarde…