0
Good evening, everyone.
I am, for the sake of studies, doing a simple CRUD for managing authors. I got stuck in the part of sending a success message by registering a new author. My current structure is as follows:
--- autores
--- autores-create
--- autores-create.component.html (página com o formulário para criação do novo autor)
--- autores-create.component.ts
--- shared
--- autores.service.ts
--- autor.model.ts
--- autores.component.html (página principal com a tabela listando todos autores)
--- autores.component.ts
--- autores.module.ts
Code of the authors.component.ts
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Autor } from './autor.model';
import { AutoresService } from './shared/autores.service';
@Component({
selector: 'app-autores',
templateUrl: './autores.component.html'
})
export class AutoresComponent implements OnInit {
message: string;
autores: Autor[];
constructor(private service: AutoresService, private router: Router) { }
ngOnInit(): void {
// Chamando o serviço para listar todos os autores
this.service.getAutores().subscribe(data => {
this.autores = data;
})
// Me inscrevendo no EventEmitter do serviço para saber quando foi gerada nova mensagem
this.service.message.subscribe(
(data: string) => { alert(data); this.message = data; }
);
}
removerAutor(id: number) {
this.service.removerAutor(id).subscribe(resultado => this.autores = this.autores.filter(autores => autores.id !== id));
}
// Apenas navega para página com formulário de criação de novo autor
criarAutor() {
this.router.navigate(['autores/create']);
}
}
Code of the authors-create.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { Autor } from './../autor.model';
import { AutoresService } from '../shared/autores.service';
@Component({
selector: 'app-autores-create',
templateUrl: './autores-create.component.html'
})
export class AutoresCreateComponent implements OnInit {
form: FormGroup;
emailPattern: "^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$";
constructor(private service: AutoresService, private route: Router) { }
ngOnInit(): void {
this.form = new FormGroup({
'nome': new FormControl(null, [Validators.required]),
'endereco': new FormControl(null, [Validators.required, Validators.minLength(5)]),
'email': new FormControl(null, [Validators.required, Validators.email]),
})
}
// Chama o método de criação de novo autor no serviço e quando finaliza navega para a página inicial com a tabela
criarAutor(data: Autor) {
this.service.criarAutor(data).subscribe((data) => {
this.route.navigate(['/autores']);
});
}
campoInvalido(campo: string) {
if (this.form.get(campo).invalid && (this.form.get(campo).dirty || this.form.get(campo).touched)) {
return this.form.get(campo).errors;
}
}
}
Code of the authors.service.ts
import { Injectable, EventEmitter, Output } from '@angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { Autor } from '../autor.model';
@Injectable({
providedIn: 'root'
})
export class AutoresService {
API_URL: string = 'http://localhost:3000';
// Campo de mensagem que seria exibida na página da tabela indicando que o novo autor foi criado com sucesso
@Output() message: EventEmitter<string> = new EventEmitter<string>();
constructor(private http: HttpClient) { }
httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'my-auth-token'
})
};
getAutores(): Observable<Autor[]> {
return this.http.get<Autor[]>(`${this.API_URL}/autores`)
.pipe(catchError(this.handleError));
}
removerAutor(id: number) {
return this.http.delete(`${this.API_URL}/autores/${id}`, this.httpOptions)
.pipe(catchError(this.handleError));
}
criarAutor(dados: Autor) {
// Emissão do evento ao criar novo autor
this.message.emit("Autor criado com sucesso.")
return this.http.post(`${this.API_URL}/autores`, dados, this.httpOptions)
.pipe(catchError(this.handleError));
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
// return an observable with a user-facing error message
return throwError(
'Something bad happened; please try again later.');
};
}
Code of the authors.component.html
<div class="container py-5">
<div class="row">
<div class="col-md-12 mb-5 d-flex justify-content-between align-items-center">
<h1 class="d-inline">Autores</h1>
<button (click)="criarAutor()" class="btn btn-success">+ autor</button>
</div>
<!-- Aqui deveria aparecer a mensagem -->
<div class="alert alert-success">{{ message }}</div>
<div class="col-md-12">
<table *ngIf="autores?.length > 0" class="table" style="table-layout: fixed;">
<thead>
<th>ID</th>
<th>Nome</th>
<th>Ações</th>
</thead>
<tbody>
<tr *ngFor="let autor of autores">
<td>{{ autor.id }}</td>
<td>{{ autor.nome }}</td>
<td>
<button class="btn btn-warning mr-3">Editar</button>
<button (click)="removerAutor(autor.id)" class="btn btn-danger">Remover</button>
</td>
</tr>
</tbody>
</table>
<p *ngIf="autores?.length === 0">Não existem autores cadastrados.</p>
</div>
</div>
</div>
What I found more strange is that in the file authors.component.ts, specifically in this code snippet:
this.service.message.subscribe(
(data: string) => { alert(data); this.message = data; }
);
Alert is working correctly but the message is not exchanged! Would anyone have any suggestions? I would like to do this without using libraries ready to fix my learning.
I don’t know if that’s the case, but here’s the code of the authors.module.ts
import { RouterModule } from '@angular/router';
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http'
import { ReactiveFormsModule } from '@angular/forms';
import { AutoresService } from './shared/autores.service';
import { AutoresComponent } from './autores.component';
import { AutoresCreateComponent } from './autores-create/autores-create.component';
@NgModule({
declarations: [AutoresComponent, AutoresCreateComponent],
imports: [CommonModule, HttpClientModule, RouterModule, ReactiveFormsModule],
providers: [AutoresService]
})
export class AutoresModule { }
And finally, here’s the contents of my app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AutoresModule } from './autores/autores.module';
import { AppComponent } from './app.component';
import { HeaderComponent } from './components/header/header.component';
import { HomeComponent } from './home/home.component';
import { RouterModule } from '@angular/router';
@NgModule({
declarations: [
AppComponent,
HeaderComponent,
HomeComponent
],
imports: [
BrowserModule,
AutoresModule,
AppRoutingModule,
RouterModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
So when you say: Alert is working correctly but the message is not exchanged!, the alert will definitely be triggered because it is in the
NgOnInit()
and when the component is rendered Angular automatically calls this method. I think the error might be this eventEmitter pq it works to make communication from the child component to the parent component, but, by the hierarchy that put in the question, all components are brothers one of the others.– LeAndrade
Yes but Alert is inside the subscribe, not loose in Ngoninit().. That is, I’m just seeing that Alert after going on the form page and giving Ubmit on it.. and the alert is coming with the right message, the variable data. Throwing that date into my this.message is that nothing happens.
– Guilherme Gomes