Angular-Loiane-Training

Este repositorio contem exemplos documentados e descricoes dos conteudos estudados ao longo do curso de Angular da Loiane

View project on GitHub

Rotas Filhas: Desenvolvendo Telas

Vamos desenvolver as telas para os components criados na documentação Rotas Filhas utilizando o Materialize CSS.

Dados Mockados

Para simular os dados oriundos de um back-end vamos criar uma classe de serviço que sera nosso objeto Mock.

  • Classe Mock (AlunosService)
import { Injectable } from '@angular/core';

@Injectable()
export class AlunosService {

  private _alunos: any[] = [
    {id: 1, nome: 'Aluno01', email: 'aluno01@email.com'},
    {id: 2, nome: 'Aluno02', email: 'aluno02@email.com'},
    {id: 3, nome: 'Aluno03', email: 'aluno03@email.com'}
  ]

  constructor() { }

  getAlunos(): any {
    return this._alunos
  }

  getAluno(id: number): any {
    for(const aluno of this._alunos){
      if(aluno.id == id) return aluno
    }
    return null
  }
}

Observe que temos 2 métodos, um para retornar todos os alunos (getAlunos()) e outro para retornar apenas um aluno (getAluno(id)) recebendo seu id como argumento.

OBS: como esta e uma classe Mock nenhum algoritmo para performance de busca foi implementado, pois, sao apenas dados em pequenas quantidades, e a estrutura de repetição for serve bem para este proposito.

IMPORTANTE: note que para este exemplo no decorator @Injectable() não ha um objeto com o atributo providedIn: 'root', deste modo e necessário declarar a qual modulo esta classe de serviço pertence, seguindo a estrutura do projeto deve ser declarada em alunos.module.ts no array providers, a classe Mock estará disponível para todos os compoenents declarados no modulo e todos os components dos módulos que importarem o modulo AlunosModule.

//...demais imports omitidos
import { AlunosService } from './alunos.service';

@NgModule({
  declarations: [
    //...demais components omitidos
  ],
  imports: [
    //...demais modulos omitidos
  ],
  exports: [],
  providers: [ AlunosService ]
})
export class AlunosModule { }

Desenvolvendo telas

Lista de Alunos

Para recuperar os dados em AlunosComponent iremos injetar por injeção de dependências do Angular no construtor, no método ngOnInit() aramazenar os dados mockados no atributo alunos da classe AlunosComponent.

import { AlunosService } from './alunos.service';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-alunos',
  templateUrl: './alunos.component.html',
  styleUrls: ['./alunos.component.css']
})
export class AlunosComponent implements OnInit {

  public alunos: any[]

  constructor(private _service: AlunosService) { }

  ngOnInit(): void {
    this.alunos = this._service.getAlunos()
  }
}

No template HTML DOM irmos utilizar a lista da seção Collections do Materialize CSS, a diretiva ngFor ira renderizar os alunos obtidos no array alunos da class AlunosComponent

<div class="row">
  <div class="col s6">
    <p>Lista de Alunos</p>
    <div class="collection">
      <a
      *ngFor="let aluno of alunos"
        class="collection-item"
        [routerLink]="[aluno.id]"
        routerLinkActive="active"
      >
      
      </a>
    </div>
  </div>
  <div class="col s6">
    <router-outlet></router-outlet>
  </div>
</div>

Note que no em [routerLink] não e necessário passar o caminho /alunos pois por se tratar de uma rota filha todos os argumentos de caminho passados para a url serão inseridos apos a rota do component pai, logo basta passar o id do aluno desejado que a rota completa sera /alunos/:id, onde :id e o id do aluno desejado.

Importante: para o funcionamento correto do materialize CSS segundo o exemplo obtido em Grid e importante que todo o contudo esteja no interior de uma div com a class container, esta classe esta como valor do atributo class em app.component.html, ou seja, engloba toda a aplicação. Neste exemplo a tela esta dividida ao meio entre a lista de alunos e as rotas filhas.

Rotas Filhas (AlunosDetalhe e AlunosForm)

Alunos Detalhe

Na classe AlunoDetalheComponent também iremos utilizar um objeto Mock do tipo que foi criado no inicio deste documento, mas desta vez para obter os dados de um único aluno, a classe ActivatedRoute do package @angular/router também sera utilizada para obter o id do aluno a partir dos parâmetros passados para a rota por meio do método subscribe() para obter o valor do parâmetro id e passa-lo como argumento ao método getAluno(id) e retornar os dados de um aluno especifico.

import { Subscription } from 'rxjs';
import { AlunosService } from './../alunos.service';
import { ActivatedRoute } from '@angular/router';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-aluno-detalhe',
  templateUrl: './aluno-detalhe.component.html',
  styleUrls: ['./aluno-detalhe.component.css']
})
export class AlunoDetalheComponent implements OnInit {

  public aluno: any
  private inscricao: Subscription

  constructor(private _route: ActivatedRoute, private _service: AlunosService) { }

  ngOnInit(): void {
    this.inscricao = this._route.params.subscribe((params: any) => {
      let id = params['id']
      this.aluno = this._service.getAluno(id)
    })
  }

  ngOnDestroy() {
    this.inscricao.unsubscribe()
  }

}

no DOM basta apenas exibir os valores recebidos por meio de interpolacao

<p>Detalhe Aluno</p>

<p>Id: </p>
<p>Nome: </p>
<p>E-mail:  </p>

Formulário para adição/edição de alunos

Do mesmo modo que o AlunoDetalheCompoenent busca o objeto de um aluno com base em seu id, AlunoFormComponent também tera a mesma logica.

import { Subscription } from 'rxjs';
import { AlunosService } from './../alunos.service';
import { ActivatedRoute } from '@angular/router';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-alunos-form',
  templateUrl: './alunos-form.component.html',
  styleUrls: ['./alunos-form.component.css']
})
export class AlunosFormComponent implements OnInit {

  public aluno: any
  private inscricao: Subscription

  constructor(private _route: ActivatedRoute, private _service: AlunosService) { }

  ngOnInit(): void {
    this.inscricao = this._route.params.subscribe((params) => {
      this.aluno = this._service.getAluno(params['id'])
    })
  }

  ngOnDestroy(): void {
    this.inscricao.unsubscribe()
  }
}

No DOM os dados serão exibidos em um formulário modificado a partir dos modelos em Forms do Materialize CSS. Utilizando a diretiva ngModel do angular para realizar o two-way-data-binding.

IMPORTANTE: lembre-se que para utilizar a diretiva ngModel o modulo FormsModule, deve ser importado no módulo que declara os components que iram utilizar a diretiva.

  • modulo AlunosModule
//...demais imports omitidos
import { FormsModule } from '@angular/forms';

@NgModule({
  declarations: [
    //...components declarados omitidos
  ],
  imports: [
    //...demais modulos importados omitidos
    FormsModule
  ],
  exports: [],
  providers: [ 
    //...providers importados omitidos
   ]
})
export class AlunosModule { }
  • dom
<h5>
  Criar/Editar Aluno
</h5>

<div class="col s12">
  <div class="row">
    <div class="col s12">
      <label for="Id">#</label>
      <input disabled [(ngModel)]="aluno.id" id="id" type="text">
    </div>
  </div>
  <div class="row">
    <div class="col s12">
      <label for="nome" class="active">Nome</label>
      <input id="nome" [(ngModel)]="aluno.nome" type="text">
    </div>
  </div>
  <div class="row">
    <div class="col s12">
      <label for="email">Email</label>
      <input id="email" [(ngModel)]="aluno.email" type="email">
    </div>
  </div>
</div>

Note que não foi utilizada a tag form, este assunto sera abortado posteriormente, o Angular e inteligente para detectar forms, logo, podemos utilizar a tag div no lugar da tag form.

Adição do botão para editar no component AlunoDetalheComponent

para redirecionar para a AlunoFormComponent utilizaremos as rotas imperativas o método btnEditarAluno() que sera chamado por meio de um botão no DOM de AlunoDetalheComponent

  • classe AlunoDetalheComponent
// ...demais imports omitidos
import { ActivatedRoute, Router } from '@angular/router';

@Component({
  selector: 'app-aluno-detalhe',
  templateUrl: './aluno-detalhe.component.html',
  styleUrls: ['./aluno-detalhe.component.css']
})
export class AlunoDetalheComponent implements OnInit {

  // ...atributos da classe omitidos

  constructor(
    // ...demais parametros do construtos omitidos
    private _router: Router,

  ) { }

  // ...demais metodos da classe omitidos

  btnEditarAluno() {
    this._router.navigate(['/alunos', this.aluno.id, 'editar'])
  }

}
  • adição do botão no DOM de AlunoDetalheComponent
<!-- codigo HTML omitido -->

<a
  class="waves-effect waves-light btn"
  (click)="btnEditarAluno()"
>
  Editar
</a>

Utilizando Telas Desenvolvidas


exemplo das telas desenvolvidas.