Servicios
Primero vamos a crear nuestras variables environment para conectar al api rest nos vamos al directorio environments y en el archivo environment.ts esto es en la parte de desarrollo.
export const environment = {
production: false,
urlHost:'http://localhost:8080/',
urlApi:'http://localhost:8080/api/v1'
};
A continuación vamos a crear nuestro servicio con el siguiente comando
ng g s services/login

En la carpeta services creamos archivo llamado loginRequest.ts que va hacer una interface
export interface LoginRequest {
username:string,
password:string
}
En la carpeta services creamos el archivo llamado autresponse.ts que va hacer una interface
export interface Autresponse{
token:string;
username:string;
}
En el archivo login.service.ts escribimos lo siguiente
import { Injectable } from '@angular/core';
import { LoginRequest } from './loginRequest';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, catchError, throwError,BehaviorSubject, tap, map } from 'rxjs';
import { Administrador } from './administrador';
import { Autresponse } from './autresponse';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class LoginService {
currentAdministradorLoginOn:BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
currentAdministradorData:BehaviorSubject<String>=new BehaviorSubject<String>("");
currentAdmin:BehaviorSubject<Autresponse>=new BehaviorSubject<Autresponse>({token:'',username:''});
constructor(private http:HttpClient) {
this.currentAdministradorLoginOn=new BehaviorSubject<boolean>(sessionStorage.getItem("token")!=null);
this.currentAdministradorData=new BehaviorSubject<String>(sessionStorage.getItem("token") || "");
this.currentAdmin=new BehaviorSubject<Autresponse>({token:'',username:''})
}
login(credentials:LoginRequest):Observable<Autresponse>{
return this.http.post<Autresponse>(environment.urlHost+"auth/login",credentials).pipe(
tap((userData)=>{
sessionStorage.setItem("token",userData.token);
this.currentAdmin.next(userData);
this.currentAdministradorData.next(userData.token);
this.currentAdministradorLoginOn.next(true);
}),
catchError(this.handleError)
)
}
private handleError(error:HttpErrorResponse){
if(error.status===0){
console.error('Se ha producio un error ', error.error);
}
else{
console.error('Backend retornó el código de estado ', error);
}
return throwError(()=> new Error('Algo falló. Por favor intente nuevamente.'));
}
logout():void{
sessionStorage.removeItem("token");
this.currentAdministradorLoginOn.next(false);
}
get userData():Observable<Autresponse>{
return this.currentAdmin.asObservable();
}
get userLoginOn():Observable<boolean>{
return this.currentAdministradorLoginOn.asObservable();
}
}
creamos el servicio administrador
ng g s services/administrador

En la carpeta services creamos archivo llamado administrador.ts que va hacer una interface
export interface Administrador{
idAdmin:number;
nombre:string;
apellidoPaterno:string;
apellidoMaterno?:string;
correo:string;
celular:string;
rol:string;
}
En el archivo administrador.service.ts escribimos lo siguiente
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, catchError,throwError } from 'rxjs';
import { Administrador } from './administrador';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class AdministradorService {
constructor(private http:HttpClient) {}
getAdministrador(email:string):Observable<Administrador>
{
return this.http.get<Administrador>(environment.urlApi+"/admin/"+email).pipe(
catchError(this.handleError)
)
}
private handleError(error:HttpErrorResponse){
if(error.status===0){
console.error('Se ha producio un error ', error.error);
}
else{
console.error('Backend retornó el código de estado ', error.status, error.error);
}
return throwError(()=> new Error('Algo falló. Por favor intente nuevamente.'));
}
}
Invocando los Servicios
Para mandar a llamar nuestro servicio que creamos tenemos que modificar los siguinetes archivos.Abrimos el archivo login.component.ts y lo dejamos de la siguiente forma
import { Component, OnInit } from '@angular/core';
import {AbstractControl, FormBuilder,Validators} from '@angular/forms';
import { Router } from '@angular/router';
import { LoginService } from 'src/app/services/login.service';
import { LoginRequest } from 'src/app/services/loginRequest';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
loginError:string="";
loginForm=this.formBuilder.group({
username:['',[Validators.required,Validators.email]],
password:['',Validators.required],
}
)
constructor(private formBuilder:FormBuilder,private router:Router,
private loginService:LoginService) { }
ngOnInit(): void {
}
get f(): { [key: string]: AbstractControl } {
return this.loginForm.controls;
}
login(){
if(this.loginForm.valid){
this.loginService.login(this.loginForm.value as LoginRequest).subscribe({
next:(userData)=>{
console.log(userData);
},
error:(errorData)=>{
console.error(errorData);
this.loginError=errorData;
},
complete:()=>{
console.info("Login completo");
this.router.navigateByUrl('/inicio');
this.loginForm.reset();
}
})
}else{
this.loginForm.markAllAsTouched();
//alert("Ingresar los datos correctamente");
}
}
}
En el código anterior se modifico la variable username por lo tanto tenemos que modificar el archivo login.component.html
<mat-card class="example-card">
<mat-card-title>Introduce tus datos</mat-card-title>
<mat-card-content>
<form [formGroup]="loginForm">
<p class="text-danger">{{loginError}}</p>
<p>
<mat-form-field>
<input type="text" formControlName="username" matInput placeholder="Email" formControlName="username">
</mat-form-field>
</p>
<div *ngIf="f['username'].invalid && (f['username'].dirty || f['username'].touched)" class="text-danger">
<div *ngIf="f['username'].errors?.['required']">
El Email es requerido.
</div>
<div *ngIf="f['username'].errors?.['email']">
El Email debe tener un formato válido.
</div>
</div>
<p>
<mat-form-field>
<input type="password" formControlName="password" matInput placeholder="Password" formControlName="password">
</mat-form-field>
</p>
<div *ngIf="f['password'].invalid && (f['password'].dirty || f['password'].touched)" class="text-danger">
<div *ngIf="f['password'].errors?.['required']">
El Password es requerido.
</div>
</div>
<div class="button">
<button type="submit" (click)="login()" mat-button>Acceder</button>
</div>
</form>
</mat-card-content>
</mat-card>
Nos vamos al archivo dashboard.component.ts lo dejamos de la siguiente manera
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Administrador } from 'src/app/services/administrador';
import { AdministradorService } from 'src/app/services/administrador.service';
import { Autresponse } from 'src/app/services/autresponse';
import { LoginService } from 'src/app/services/login.service';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {
errorMessage:String="";
userLoginOn:boolean=false;
userData?:Autresponse;
admin?:Administrador;
constructor(private loginService:LoginService,private adminService:AdministradorService) { }
ngOnInit(): void {
this.loginService.currentAdministradorLoginOn.subscribe(
{
next:(userLoginOn)=>{
this.userLoginOn=userLoginOn;
}
}
);
this.loginService.currentAdmin.subscribe(
{
next:(userData)=>{
this.userData=userData;
console.log("Probando:"+this.userData.username);
this.adminService.getAdministrador(userData.username).subscribe({
next: (adminData) => {
this.admin=adminData;
},
error: (errorData) => {
this.errorMessage=errorData
},
complete: () => {
console.info("User Data ok");
}
})
}
}
);
}
}
El archivo dashboard.component.html queda de la siguiente forma
<app-menu></app-menu>
<mat-card class="example-card">
<mat-card-title>
<p *ngIf="!userLoginOn">Usuario NO autenticado</p>
<p *ngIf="userLoginOn">Usuario Autenticado</p>
</mat-card-title>
<mat-card-content>
<div *ngIf="userLoginOn">
<p>Nombre: {{admin?.nombre}}</p>
<p>Apellidos: {{admin?.apellidoPaterno}} {{admin?.apellidoMaterno}}</p>
<p>Email: {{admin?.correo}}</p>
</div>
</mat-card-content>
</mat-card>
Modifica el archivo menu.component.ts
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { LoginService } from 'src/app/services/login.service';
@Component({
selector: 'app-menu',
templateUrl: './menu.component.html',
styleUrls: ['./menu.component.css']
})
export class MenuComponent implements OnInit {
userLoginOn:boolean=false;
constructor(private loginService:LoginService, private router:Router) { }
ngOnInit(): void {
this.loginService.currentAdministradorLoginOn.subscribe(
{
next:(userLoginOn)=>{
this.userLoginOn=userLoginOn;
}
}
)
}
logout()
{
this.loginService.logout();
this.router.navigate(['/inicio'])
}
}
El archivo menu.component.html queda de la siguiente forma
<button mat-button [matMenuTriggerFor]="inicioMenu">Inicio</button>
<mat-menu #inicioMenu="matMenu" yPosition="above">
<button *ngIf="!userLoginOn" mat-menu-item routerLink="/login">Iniciar Sesión</button>
<button *ngIf="userLoginOn" (click)="logout()" mat-menu-item routerLink="/inicio">Cerrar Sesión</button>
</mat-menu>
Probando
No hay que olvidar que para que funcione esto hay que correr el api rest y posteriormente nuestro proyecto en angular.Registrar Administrador
Primero vamos a crear un servicio para invocar la validación que si eres adminstrador con pefil ADMIN puedes ver el formulario para agregar administradores y si eres Administrador USER no tienes permiso.Creamos el servicio llamado helper con el siguiente comando
ng c s services/helper
En el archivo helper.service.ts escribimos lo siguiente:
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class HelperService {
private rolAdminOn = new BehaviorSubject(false);
public customRolOn = this.rolAdminOn.asObservable();
constructor() { }
public validaAdmin(rolAdmin:boolean){
this.rolAdminOn.next(rolAdmin);
}
}
Modificamos el archivo dashboard.component.ts para realizar la validación ya de aqui tomamos el datos del rol
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Administrador } from 'src/app/services/administrador';
import { AdministradorService } from 'src/app/services/administrador.service';
import { Autresponse } from 'src/app/services/autresponse';
import { HelperService } from 'src/app/services/helper.service';
import { LoginService } from 'src/app/services/login.service';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {
errorMessage:String="";
userLoginOn:boolean=false;
userData?:Autresponse;
admin?:Administrador;
userAdminOn=false;
constructor(private loginService:LoginService,private adminService:AdministradorService,
private helper: HelperService
) { }
ngOnInit(): void {
this.loginService.currentAdministradorLoginOn.subscribe(
{
next:(userLoginOn)=>{
this.userLoginOn=userLoginOn;
}
}
);
this.loginService.currentAdmin.subscribe(
{
next:(userData)=>{
this.userData=userData;
console.log("Probando:"+this.userData.username);
this.adminService.getAdministrador(userData.username).subscribe({
next: (adminData) => {
this.admin=adminData;
console.log(adminData.rol);
if( adminData.rol == 'ADMIN'){
let adminOn=true;
this.helper.customRolOn.subscribe(adminOn => this.userAdminOn = adminOn);
this.helper.validaAdmin(adminOn);
}else{
let adminOn=false;
this.helper.customRolOn.subscribe(adminOn => this.userAdminOn = adminOn);
this.helper.validaAdmin(adminOn);
}
},
error: (errorData) => {
this.errorMessage=errorData
},
complete: () => {
console.info("User Data ok");
}
})
}
}
);
}
}
Modificamos el archivo administrador.service.ts en el cual generamos el servicio crearAdminstrador
import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, catchError,throwError } from 'rxjs';
import { Administrador } from './administrador';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class AdministradorService {
private httpHeaders = new HttpHeaders({'Content-Type':'application/json'})
constructor(private http:HttpClient) {}
getAdministrador(email:string):Observable<Administrador>
{
return this.http.get<Administrador>(environment.urlApi+"/admin/"+email).pipe(
catchError(this.handleError)
)
}
crearAdministrador(admin:Administrador):Observable<Administrador>
{
return this.http.post<Administrador>(environment.urlApi+"/admin",admin).pipe(
catchError(this.handleError)
)
}
private handleError(error:HttpErrorResponse){
if(error.status===0){
console.error('Se ha producio un error ', error.error);
}
else{
console.error('Backend retornó el código de estado ', error.status, error.error);
}
return throwError(()=> new Error('Algo falló. Por favor intente nuevamente.'));
}
}
Lo que sigue es que vamos a crear un dialogo para que cuando insertemos nuestro administador nos avise.Creamos el componente createuserdialog con el siguiente comando:
ng g c dashboard/createuserdialog
En el archivo createuserdialog.component.html escribimos lo siguiente:
<h1 mat-dialog-title>Administrador Insertado</h1>
<div mat-dialog-content>Administrador fue insertado.</div>
<div mat-dialog-actions>
<button mat-button mat-dialog-close>Close</button>
</div>
En el archivo app.module.ts agregamos el MatDialogModule
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HeaderComponent } from './shared/header/header.component';
import { FooterComponent } from './shared/footer/footer.component';
import { LoginComponent } from './pages/login/login.component';
import { DashboardComponent } from './pages/dashboard/dashboard.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {MatMenuModule} from '@angular/material/menu';
import {MatButtonModule} from '@angular/material/button';
import {MatCardModule} from '@angular/material/card';
import { MenuComponent } from './shared/menu/menu.component';
import { MatInputModule} from '@angular/material/input';
import { ReactiveFormsModule } from '@angular/forms';
import {HTTP_INTERCEPTORS, HttpClientModule} from '@angular/common/http';
import { FormadminComponent } from './dashboard/formadmin/formadmin.component';
import { CreateuserdialogComponent } from './dashboard/createuserdialog/createuserdialog.component';
import {MatDialogModule} from '@angular/material/dialog';
@NgModule({
declarations: [
AppComponent,
HeaderComponent,
FooterComponent,
LoginComponent,
DashboardComponent,
MenuComponent,
FormadminComponent,
CreateuserdialogComponent
],
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
MatMenuModule,
MatButtonModule,
MatCardModule,
MatInputModule,
ReactiveFormsModule,
HttpClientModule,
MatDialogModule
],
providers: [
],
bootstrap: [AppComponent]
})
export class AppModule { }
Ahora vamos a crear el componente para nuestro formulario que va craer el administrador lo vamos a llamar formadmin
ng g c dashboard/formadmin
En el archivo formadmin.component.ts escribimos lo siguiente:
import { Component, OnInit } from '@angular/core';
import {AbstractControl, FormBuilder,Validators} from '@angular/forms';
import { Router } from '@angular/router';
import {MatDialog} from '@angular/material/dialog';
import { CreateuserdialogComponent } from '../createuserdialog/createuserdialog.component';
import { AdministradorService } from 'src/app/services/administrador.service';
import { Administrador } from 'src/app/services/administrador';
import { HelperService } from 'src/app/services/helper.service';
@Component({
selector: 'app-formadmin',
templateUrl: './formadmin.component.html',
styleUrls: ['./formadmin.component.css']
})
export class FormadminComponent implements OnInit {
public userAdminOn:boolean=false;
adminError:string="";
adminForm=this.formBuilder.group({
nombre:['',Validators.required],
apellidoPaterno:['',Validators.required],
apellidoMaterno:'',
correo:['',[Validators.required,Validators.email]],
celular:['',[Validators.required,Validators.pattern("^[0-9]*$")]],
password:['',Validators.required],
rol:''
}
)
constructor(private formBuilder:FormBuilder,public dialog: MatDialog,
private adminService:AdministradorService,private router:Router,
private helper: HelperService
) { }
ngOnInit(): void {
this.helper.customRolOn.subscribe(
{
next:(userAdminOn)=>{
this.userAdminOn=userAdminOn;
console.log("El dato es igual:"+this.userAdminOn);
}
}
);
}
get f(): { [key: string]: AbstractControl } {
return this.adminForm.controls;
}
insertarAdmin(){
if(this.adminForm.valid){
this.adminService.crearAdministrador(this.adminForm.value as Administrador).subscribe({
next:(userData)=>{
console.log(userData);
},
error:(errorData)=>{
console.error(errorData);
this.adminError=errorData;
},
complete:()=>{
this.dialog.open(CreateuserdialogComponent);
this.router.navigateByUrl('/inicio');
this.adminForm.reset();
}
})
}
else{
this.adminForm.markAllAsTouched();
//alert("Ingresar los datos correctamente");
}
}
}
En el archivo formadmin.component.html escribimos lo siguiente:
<app-menu></app-menu>
<mat-card class="example-card">
<div *ngIf="userAdminOn">
<mat-card-content>
<mat-card-title>Crear Administrador</mat-card-title>
<form [formGroup]="adminForm">
<p class="text-danger">{{adminError}}</p>
<p>
<mat-form-field>
<input type="text" formControlName="nombre" matInput placeholder="Introducir Nombre">
</mat-form-field>
</p>
<div *ngIf="f['nombre'].invalid && (f['nombre'].dirty || f['nombre'].touched)" class="text-danger">
<div *ngIf="f['nombre'].errors?.['required']">
El nombre es requerido.
</div>
</div>
<p>
<mat-form-field>
<input type="text" formControlName="apellidoPaterno" matInput placeholder="Introducir Apellido Paterno">
</mat-form-field>
</p>
<div *ngIf="f['apellidoPaterno'].invalid && (f['apellidoPaterno'].dirty || f['apellidoPaterno'].touched)" class="text-danger">
<div *ngIf="f['apellidoPaterno'].errors?.['required']">
El apellido paterno es requerido.
</div>
</div>
<p>
<mat-form-field>
<input type="text" formControlName="apellidoMaterno" matInput placeholder="Introducir Apellido Materno">
</mat-form-field>
</p>
<p>
<mat-form-field>
<input type="text" formControlName="correo" matInput placeholder="Introducir email">
</mat-form-field>
</p>
<div *ngIf="f['correo'].invalid && (f['correo'].dirty || f['correo'].touched)" class="text-danger">
<div *ngIf="f['correo'].errors?.['required']">
El Email es requerido.
</div>
<div *ngIf="f['correo'].errors?.['email']">
El Email debe tener un formato válido.
</div>
</div>
<p>
<mat-form-field>
<input type="text" formControlName="celular" matInput placeholder="Introducir celular">
</mat-form-field>
</p>
<div *ngIf="f['celular'].invalid && (f['celular'].dirty || f['celular'].touched)" class="text-danger">
<div *ngIf="f['celular'].errors?.['required']">
El celular es requerido.
</div>
<div *ngIf="f['celular'].errors?.['pattern']">
Meter solo números.
</div>
</div>
<p>
<mat-form-field>
<input type="password" formControlName="password" matInput placeholder="Introducir Password" autocomplete="on">
</mat-form-field>
</p>
<div *ngIf="f['password'].invalid && (f['password'].dirty || f['password'].touched)" class="text-danger">
<div *ngIf="f['password'].errors?.['required']">
El Password es requerido.
</div>
</div>
<mat-form-field appearance="fill">
<mat-label>Perfil Administrador</mat-label>
<select matNativeControl required formControlName="rol">
<option value="USER" selected>Usuario</option>
<option value="ADMIN">Administrador</option>
</select>
</mat-form-field>
<div class="button">
<button type="submit" (click)="insertarAdmin()" mat-raised-button color="primary">Registrar Administrador</button>
</div>
</form>
</mat-card-content>
</div>
<div *ngIf="!userAdminOn">
<mat-card-content>
<mat-card-title>No tienes permiso para agregar administradores</mat-card-title>
</mat-card-content>
</div>
</mat-card>
Vamos a crear la funcionalidad de crear administrador, primero vamos a crear la ruta y modificando el archivo app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { DashboardComponent } from './pages/dashboard/dashboard.component';
import { LoginComponent } from './pages/login/login.component';
import { FormadminComponent } from './dashboard/formadmin/formadmin.component';
const routes: Routes = [
{path:'',redirectTo:'/inicio', pathMatch:'full'},
{path:'inicio',component:DashboardComponent},
{path:'login',component:LoginComponent},
{path:'crearAdmin',component:FormadminComponent}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Lo que sigue es modificar el menú para invocar la funcionalidad modifcamos el archivo menu.component.html
<button mat-button [matMenuTriggerFor]="inicioMenu">Inicio</button>
<mat-menu #inicioMenu="matMenu" yPosition="above">
<button *ngIf="!userLoginOn" mat-menu-item routerLink="/login">Iniciar Sesión</button>
<button *ngIf="userLoginOn" mat-menu-item routerLink="/crearAdmin">Crear Administrador</button>
<button *ngIf="userLoginOn" (click)="logout()" mat-menu-item routerLink="/inicio">Cerrar Sesión</button>
</mat-menu>
Espero que no me hayga faltado alguna parte código sino reportar a kapo1978@hotmail.com y en breve te contesto.Ahora corremos la aplicación: