Ebben a leírásban dolgozók adatait fogjuk kezelni, a teljes CRUD műveleteket megvalósítva, azonosítással. A megvalósításhoz szükséges egy REST API kiszolgáló.
Szükségünk van egy REST API szerverre, a következő végpontokkal. Ennek elkészítését lásd Laravel API leírásban
Végpont | Metódus | Auth | CRUD | Leírás |
---|---|---|---|---|
/employees | GET | nem | read | összes dolgozó |
/employees | POST | igen | create | új dolgozó |
/employees/{id} | GET | nem | read | egy dolgozó |
/employees/{id} | PUT | igen | update | dolgozó frissítése |
/employees/{id} | DELETE | igen | delete | dolgozó törlése |
/register | POST | nem | n/a | regisztráció |
/login | POST | nem | n/a | belépés |
/logout | POST | nem | n/a | kilépés |
A backend elérhető a GitHubon a következő címen:
Beüzemelés a projekt docs könyvtárában.
Készítsünk egy angular projektet:
ng new app01
Kérjünk router szolgáltatást.
Lépjünk be, majd indítsunk kódszerkesztőt.
cd app01 code .
import { HttpClientModule } from '@angular/common/http'; //... imports: [ HttpClientModule ],
Készítsünk egy szolgáltatást, auth néven:
ng generate service shared/auth
Létrejön két fájl:
Importáljuk a HttpClient és HttpHeaders osztályokat:
import { HttpClient, HttpHeaders } from '@angular/common/http';
host = 'http://localhost:8000/api/';
A konstruktorba paraméterként vegyük fel a http objektumot:
constructor(private http: HttpClient) { }
A login() metódus:
login(user: string, pass: string) { const authData = { name: user, password: pass } let httpHeaders = new HttpHeaders(); httpHeaders.set('Content-Type', 'application/json'); const httpOptions = { headers: httpHeaders } let endpoint = 'login'; let url = this.host + endpoint; return this.http.post<any>(url, authData, httpOptions); }
import { ReactiveFormsModule } from '@angular/forms'; //... imports: [ ReactiveFormsModule ], //...
Készítsük el az employee komponenst:
ng generate component login
Elsőként importáljuk az AuthService osztályt:
//... import { FormBuilder, FormGroup } from '@angular/forms'; import { AuthService } from '../shared/auth.service'; //...
Injektáljuk és használjuk:
//... export class LoginComponent implements OnInit { loginForm !: FormGroup; constructor( private auth: AuthService, private formBuilder: FormBuilder ) { } ngOnInit(): void { this.loginForm = this.formBuilder.group({ user: [''], pass: [''] }); } login() { let user = this.loginForm.value.user; let pass = this.loginForm.value.pass; this.auth.login(user, pass).subscribe({ next: data => { localStorage.setItem('userData', JSON.stringify(data)); }, error: err => { console.log('Hiba! A belépés sikertelen!') } }); } }
A válasz részletezése:
console.log(res.name); console.log(res.token);
<h3>Belépés</h3> <form [formGroup]="loginForm" (submit)="login()"> <div class="mb-3"> <label for="user" class="form-label">Felhasználónév</label> <input type="text" class="form-control" id="user" formControlName="user"> </div> <div class="mb-3"> <label for="pass" class="form-label">Jelszó</label> <input type="pass" class="form-control" id="exampleInputPassword1" formControlName="pass"> </div> <button type="submit" class="btn btn-primary">Belépés</button> </form>
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { LoginComponent } from './login/login.component'; const routes: Routes = [ { path: 'login', component: LoginComponent} ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
//... logout(name: string, token: string) { const userData = { name: name, tokenId: token } let httpHeaders = new HttpHeaders(); httpHeaders.set('Content-Type', 'application/json'); const httpOptions = { headers: httpHeaders } let endpoint = 'logout'; let url = this.host + endpoint; console.log(userData.name) return this.http.post<any>(url, userData, httpOptions); }
<ul> <li> <a routerLink="/employees">Dolgozók</a> </li> <li> <a routerLink="/login">Login</a> </li> </ul> <button (click)="logout()">Kilépés</button> <router-outlet></router-outlet>
import { Component } from '@angular/core'; import { AuthService } from './shared/auth.service'; //... export class AppComponent { title = 'app01'; constructor(private auth: AuthService) {} logout() { let jsonUserData: any = localStorage.getItem('userData'); let userData = JSON.parse(jsonUserData); console.log(userData.name); console.log(userData.token); this.auth.logout(userData.name, userData.token).subscribe({ next: res => { console.log(res) } }); } }
Végpont | Metódus | Azonosítás | CRUD |
---|---|---|---|
/employees | GET | nem | Read |
Szükségünk van a HttpClientModule nevű modulra. Ha megcsináltuk az azonosítást, akkor ez kihagyható:
import { HttpClientModule } from '@angular/common/http'; //... imports: [ HttpClientModule ],
Készítsünk egy szolgáltatást, api néven:
ng generate service shared/api
Létrejön két fájl:
Az api.service.ts fájlba írjuk a szolgáltatást. Az api.service.spec.ts a teszt az előbbi állomány számára.
Vegyük az api.service.ts fájl, majd importáljuk a HttpClient:
import { HttpClient } from '@angular/common/http';
A konstruktorba paraméterként vegyük fel a http objektumot:
constructor(private http: HttpClient) { }
Hozzuk létre a host adattagot és a getEmployees() metódust:
//... host = 'http://localhost:8000/api/'; //... getEmployees() { let endpoint = 'employees'; let url = this.host + endpoint; return this.http.get<any>(url); }
ng generate component employee
Szerkesszük az src/app/employee/employee.component.ts fájlt.
import { Component, OnInit } from '@angular/core'; import { ApiService } from '../shared/api.service'; @Component({ selector: 'app-employee', templateUrl: './employee.component.html', styleUrls: ['./employee.component.css'] }) export class EmployeeComponent implements OnInit { employees: any; constructor(private api: ApiService) { } ngOnInit(): void { this.getEmployees(); } getEmployees() { this.api.getEmployees().subscribe({ next: data => { this.employees = data; }, error: err => { console.log('Hiba! A dolgozók letöltése sikertelen!'); } }); } }
<p>Dolgozók</p> <table> <thead> <tr> <th>Id</th> <th>Név</th> <th>Település</th> <th>Fizetés</th> </tr> </thead> <tbody> <tr *ngFor="let employee of employees"> <td>{{ employee.id }}</td> <td>{{ employee.name }}</td> <td>{{ employee.city }}</td> <td>{{ employee.salary }}</td> </tr> </tbody> </table>
const routes: Routes = [ { path: 'login', component: LoginComponent}, { path: 'employees', component: EmployeeComponent} ];
Backend oldalon van egy /api/employees végpontunk, ahol POST metódussal új dolgozókat vehetünk fel.
Végpont | Metódus | Azonosítás | CRUD |
---|---|---|---|
/employees | POST | igen | Create |
Ha még nincs regisztrálva az src/app/app.module.ts fájlban a HttpClientModule, akkor tegyük meg.
import { HttpClientModule } from '@angular/common/http'; //... imports: [ HttpClientModule ],
Ha még nem létezik, hozzuk létre az api szolgáltatást:
ng generate service shared/api
Importáljuk a HttpClient és HttpHeaders osztályokat:
import { HttpClient, HttpHeaders } from '@angular/common/http'; //...
A konstruktorba paraméterként vegyük fel a http objektumot, ha még nincs felvéve:
//... constructor(private http: HttpClient) { } //...
Hozzuk létre a addEmployee() metódust:
//... addEmployee(employee: any) { let jsonUserData: any = localStorage.getItem('userData'); let userData = JSON.parse(jsonUserData); let httpHeaders = new HttpHeaders() .set('Authorization', `Bearer ${userData.token}`); const httpOptions = { headers: httpHeaders } let endpoint = 'employees'; let url = this.host + endpoint; return this.http.post<any>(url, employee, httpOptions); }
Reaktív űrlapot fogunk használni, ezért importáljuk a FormBuilder és a FormGroup osztályt, az src/app/employee/employee.component.ts fájlban:
import { FormBuilder, FormGroup } from '@angular/forms';
Az EmployeeComponent osztályban vegyük fel a következő adattagokat, és injektáljuk FormBuilder osztályt:
export class EmployeeComponent implements OnInit { employees: any; addForm !: FormGroup; addPanel: boolean = false; constructor( private api: ApiService, private formBuilder: FormBuilder ) { } //...
Az ngOnInit() függvényben készítsük elő az űrlapot:
ngOnInit(): void { this.getEmployees(); this.addForm = this.formBuilder.group({ name: [''], city: [''], salary: [''] }); }
Írjunk itt is egy addEmployee() metódust, ami az api szolgáltatás addEmployee() metóudásával dolgozik.
addEmployee() { let employee = { name: this.addForm.value.name, city: this.addForm.value.city, salary: this.addForm.value.salary, } this.api.addEmployee(employee).subscribe({ next: res => { console.log(res) this.employees.push(res); } }); }
A hozzáadó űrlap megjelenítéséhez, rejtéséhez készítsünk egy showAddPanel() metódust:
showAddPanel() { this.addPanel = true; }
Adjuk meg a fájl elején egy gombot, a végéhez pedig fűzzünk egy űrlapot:
<!-- ... --> <button (click)="showAddPanel()">Hozzáad</button> <!-- ... --> <div *ngIf="addPanel"> <form [formGroup]="addForm" (submit)="addEmployee()"> <div> <label for="name">Név</label> <input type="text" id="name" formControlName="name"> </div> <div> <label for="city">Település</label> <input type="text" id="city" formControlName="city"> </div> <div> <label for="salary">Fizetés</label> <input type="text" formControlName="salary"> </div> <button type="submit">Mentés</button> </form> </div>
A „Hozzáad” gomb a táblázat előtt, az űrlap a táblázat után.
Végpont | Metódus | Azonosítás | CRUD |
---|---|---|---|
/employees/{id} | DELETE | igen | Delete |
Az api szolgáltatás bővítése delEmployee() metódussal, a src/app/shared/api.service.ts fájlban:
//... delEmployee(id: number) { let jsonUserData: any = localStorage.getItem('userData'); let userData = JSON.parse(jsonUserData); let httpHeaders = new HttpHeaders() .set('Authorization', `Bearer ${userData.token}`); const httpOptions = { headers: httpHeaders } let endpoint = 'employees'; let url = this.host + endpoint + '/' + id; return this.http.delete<any>(url, httpOptions); }
Az employee komponensben is megírjuk a delEmployee() metódust:
//... delEmployee(employee: any) { this.api.delEmployee(employee.id).subscribe({ next: res => { console.log(res); this.employees.forEach( (emp: any, index: number) => { if (emp.id === employee.id ) { this.employees.splice(index, 1) } }) } }); }
Fel kell vennünk egy új táblázatelemet a src/app/employee/employee.component.html fájlban:
<td> <button (click)="delEmployee(employee)">Törlés</button> </td>
A teljes táblázat így néz ki:
<table> <thead> <th>Id</th> <th>Név</th> <th>Település</th> <th>Fizetés</th> </thead> <tbody> <tr *ngFor="let employee of employees"> <td>{{ employee.id }}</td> <td>{{ employee.name }}</td> <td>{{ employee.city }}</td> <td>{{ employee.salary }}</td> <td> <button (click)="delEmployee(employee)">Törlés</button> </td> </tr> </tbody> </table>
Végpont | Metódus | Azonosítás | CRUD |
---|---|---|---|
/employees/{id} | PUT | igen | Update |
Szükség van egy updateEmployee() metódusra:
//... updateEmployee(employee: any) { let jsonUserData: any = localStorage.getItem('userData'); let userData = JSON.parse(jsonUserData); let httpHeaders = new HttpHeaders() .set('Authorization', `Bearer ${userData.token}`); const httpOptions = { headers: httpHeaders } let endpoint = 'employees'; let url = this.host + endpoint + '/' + employee.id; return this.http.put<any>(url, employee, httpOptions); }
Szükség van két új adattagra az EmployeeComponent osztályban:
editPanel: boolean = false; editForm !: FormGroup;
Az ngOnInit() metódusban inicializálni kell az editForm objektumot:
//... this.editForm = this.formBuilder.group({ id: [''], name: [''], city: [''], salary: [''] });
Kell egy metódus, ami megjeleníti a szerkesztő felületet:
showEdit(employee: any) { this.editForm.patchValue({id: employee.id}); this.editForm.patchValue({name: employee.name}); this.editForm.patchValue({city: employee.city}); this.editForm.patchValue({salary: employee.salary}); this.editPanel = true; }
Kell egy metódus amit frissíti az adatokat:
updateEmployee() { let employee = { id: this.editForm.value.id, name: this.editForm.value.name, city: this.editForm.value.city, salary: this.editForm.value.salary } this.api.updateEmployee(employee).subscribe({ next: res => { console.log(res); this.editPanel = false; this.getEmployees(); } }); }
Fűzzük az employee.component.html végéhez:
//... <div *ngIf="editPanel"> <form [formGroup]="editForm" (submit)="updateEmployee()"> <div> <label for="id">Id</label> <input type="text" id="id" formControlName="id"> </div> <div> <label for="name">Név</label> <input type="text" id="name" formControlName="name"> </div> <div> <label for="city">Település</label> <input type="text" id="city" formControlName="city"> </div> <div> <label for="salary">Fizetés</label> <input type="text" formControlName="salary"> </div> <button type="submit">Mentés</button> </form> </div>
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule } from '@angular/common/http'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { LoginComponent } from './login/login.component'; import { ReactiveFormsModule } from '@angular/forms'; import { EmployeeComponent } from './employee/employee.component'; @NgModule({ declarations: [ AppComponent, LoginComponent, EmployeeComponent ], imports: [ BrowserModule, AppRoutingModule, HttpClientModule, ReactiveFormsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
import { Component } from '@angular/core'; import { AuthService } from './shared/auth.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app01'; constructor(private auth: AuthService) {} logout() { let jsonUserData: any = localStorage.getItem('userData'); let userData = JSON.parse(jsonUserData); console.log(userData.name); console.log(userData.token); this.auth.logout(userData.name, userData.token).subscribe({ next: res => { console.log(res) } }); } }
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { EmployeeComponent } from './employee/employee.component'; import { LoginComponent } from './login/login.component'; const routes: Routes = [ { path: 'login', component: LoginComponent}, { path: 'employees', component: EmployeeComponent} ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class AuthService { host = 'http://localhost:8000/api/'; constructor(private http: HttpClient) { } login(user: string, pass: string) { const authData = { name: user, password: pass } let httpHeaders = new HttpHeaders(); httpHeaders.set('Content-Type', 'application/json'); const httpOptions = { headers: httpHeaders } let endpoint = 'login'; let url = this.host + endpoint; return this.http.post<any>(url, authData, httpOptions); } logout(name: string, token: string) { const userData = { name: name, tokenId: token } let httpHeaders = new HttpHeaders(); httpHeaders.set('Content-Type', 'application/json'); const httpOptions = { headers: httpHeaders } let endpoint = 'logout'; let url = this.host + endpoint; console.log(userData.name) return this.http.post<any>(url, userData, httpOptions); } }
import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class ApiService { host = 'http://localhost:8000/api/'; constructor(private http: HttpClient) { } getEmployees() { let endpoint = 'employees'; let url = this.host + endpoint; return this.http.get<any>(url); } addEmployee(employee: any) { let jsonUserData: any = localStorage.getItem('userData'); let userData = JSON.parse(jsonUserData); let httpHeaders = new HttpHeaders() .set('Authorization', `Bearer ${userData.token}`); const httpOptions = { headers: httpHeaders } let endpoint = 'employees'; let url = this.host + endpoint; return this.http.post<any>(url, employee, httpOptions); } delEmployee(id: number) { let jsonUserData: any = localStorage.getItem('userData'); let userData = JSON.parse(jsonUserData); let httpHeaders = new HttpHeaders() .set('Authorization', `Bearer ${userData.token}`); const httpOptions = { headers: httpHeaders } let endpoint = 'employees'; let url = this.host + endpoint + '/' + id; return this.http.delete<any>(url, httpOptions); } updateEmployee(employee: any) { let jsonUserData: any = localStorage.getItem('userData'); let userData = JSON.parse(jsonUserData); let httpHeaders = new HttpHeaders() .set('Authorization', `Bearer ${userData.token}`); const httpOptions = { headers: httpHeaders } let endpoint = 'employees'; let url = this.host + endpoint + '/' + employee.id; return this.http.put<any>(url, employee, httpOptions); } }
import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; import { AuthService } from '../shared/auth.service'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'] }) export class LoginComponent implements OnInit { loginForm !: FormGroup; constructor( private auth: AuthService, private formBuilder: FormBuilder ) { } ngOnInit(): void { this.loginForm = this.formBuilder.group({ user: [''], pass: [''] }); } login() { let user = this.loginForm.value.user; let pass = this.loginForm.value.pass; this.auth.login(user, pass).subscribe({ next: data => { localStorage.setItem('userData', JSON.stringify(data)); }, error: err => { console.log('Hiba! A belépés sikertelen!') } }); } }
<p>Belépés</p> <form [formGroup]="loginForm" (submit)="login()"> <div> <label>Felhasználónév</label> <input type="text" formControlName="user"> </div> <div> <label>Jelszó</label> <input type="password" formControlName="pass"> </div> <button type="submit">Belépés</button> </form>
import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; import { ApiService } from '../shared/api.service'; @Component({ selector: 'app-employee', templateUrl: './employee.component.html', styleUrls: ['./employee.component.css'] }) export class EmployeeComponent implements OnInit { addPanel: boolean = false; editPanel: boolean = false; employees: any; addForm !: FormGroup; editForm !: FormGroup; constructor( private api: ApiService, private formBuilder: FormBuilder ) { } ngOnInit(): void { this.getEmployees(); this.addForm = this.formBuilder.group({ name: [''], city: [''], salary: [''] }); this.editForm = this.formBuilder.group({ id: [''], name: [''], city: [''], salary: [''] }); } getEmployees() { this.api.getEmployees().subscribe({ next: data => { this.employees = data; }, error: err => { console.log('Hiba! A dolgozók letöltése sikertelen!'); } }); } addEmployee() { let employee = { name: this.addForm.value.name, city: this.addForm.value.city, salary: this.addForm.value.salary, } this.api.addEmployee(employee).subscribe({ next: res => { console.log(res) this.employees.push(res); } }); } showAddPanel() { this.addPanel = true; } delEmployee(employee: any) { this.api.delEmployee(employee.id).subscribe({ next: res => { console.log(res); this.employees.forEach( (emp: any, index: number) => { if (emp.id === employee.id ) { this.employees.splice(index, 1) } }) } }); } showEdit(employee: any) { this.editForm.patchValue({id: employee.id}); this.editForm.patchValue({name: employee.name}); this.editForm.patchValue({city: employee.city}); this.editForm.patchValue({salary: employee.salary}); this.editPanel = true; } updateEmployee() { let employee = { id: this.editForm.value.id, name: this.editForm.value.name, city: this.editForm.value.city, salary: this.editForm.value.salary } this.api.updateEmployee(employee).subscribe({ next: res => { console.log(res); this.editPanel = false; this.getEmployees(); } }); } }
<p>Dolgozók</p> <button (click)="showAddPanel()">Hozzáad</button> <table> <thead> <th>Id</th> <th>Név</th> <th>Település</th> <th>Fizetés</th> </thead> <tbody> <tr *ngFor="let employee of employees"> <td>{{ employee.id }}</td> <td>{{ employee.name }}</td> <td>{{ employee.city }}</td> <td>{{ employee.salary }}</td> <td> <button (click)="delEmployee(employee)">Törlés</button> </td> <td> <button (click)="showEdit(employee)">Szerkesztés</button> </td> </tr> </tbody> </table> <div *ngIf="addPanel"> <form [formGroup]="addForm" (submit)="addEmployee()"> <div> <label for="name">Név</label> <input type="text" id="name" formControlName="name"> </div> <div> <label for="city">Település</label> <input type="text" id="city" formControlName="city"> </div> <div> <label for="salary">Fizetés</label> <input type="text" formControlName="salary"> </div> <button type="submit">Mentés</button> </form> </div> <div *ngIf="editPanel"> <form [formGroup]="editForm" (submit)="updateEmployee()"> <div> <label for="id">Id</label> <input type="text" id="id" formControlName="id"> </div> <div> <label for="name">Név</label> <input type="text" id="name" formControlName="name"> </div> <div> <label for="city">Település</label> <input type="text" id="city" formControlName="city"> </div> <div> <label for="salary">Fizetés</label> <input type="text" formControlName="salary"> </div> <button type="submit">Mentés</button> </form> </div>
A httpHeaders objektum így is létrehozható:
const httpHeaders = new HttpHeaders() .set('Content-Type', 'application/json');
const httpHeaders = new HttpHeaders({ 'Content-Type': 'application/json' });
Ha védett lenne a dolgozók lekérése, akkor a tokent is el kellene küldenünk a lekéréskor:
Hozzuk létre a getEmployees() metódust:
getEmployees() { let url = 'http://localhost:8000/api/employees'; let token = '3|7eBr5iAUPgqQz3lxIFgC72Yh3ERO76g1MyuHNOGD'; let header = { headers: new HttpHeaders() .set('Authorization', `Bearer ${token}`) } return this.http.get<any>(url, header); }