Posted on: February 10, 2023 06:58 PM
Posted by: Renato
Views: 410
Tutorial FullStack – Angular 10 + Laravel 8 + MySQL
Angular 10 ( Frontend )
Instala Angular 10
npm install -g @angular/cli@10
ng version
1 – Create app / Crear app
ng new app-tutofox
Would you like to add Angular routing? (y/N): y
Solução de erro
https://es.stackoverflow.com/questions/450769/error-en-ng-new-angular-cli
2 – Install bootstrap / Instalar bootstrap
ng add @ng-bootstrap/ng-bootstrap
3 – Create module / Crear module
ng generate module person --routing
4 – Create component / Crear componente
ng generate component person/index
ng generate component person/create
ng generate component person/edit
5 – Create routes / Crear rutas
src/app/person/person-routing.module.ts
/.../
import { IndexComponent } from './index/index.component';
import { CreateComponent } from './create/create.component';
import { EditComponent } from './edit/edit.component';
const routes: Routes = [
{ path: 'person', redirectTo: 'person/index', pathMatch: 'full'},
{ path: 'person/index', component: IndexComponent },
{ path: 'person/create', component: CreateComponent },
{ path: 'person/edit/:idPerson', component: EditComponent }
];
/.../
6 – Create interface / Crear interface
ng generate interface person/person
src/app/person/person.ts
export interface Person {
id: number;
name: string;
email: string;
phone: number;
}
7 – Create services / Crear servicios
src/app/person/person.service.ts
ng generate service person/person
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { Person } from './person';
@Injectable({
providedIn: 'root'
})
export class PersonService {
private apiURL = "http://localhost:8000/api/person/";
httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
}
constructor(private httpClient: HttpClient) { }
getAll(): Observable<Person[]> {
return this.httpClient.get<Person[]>(this.apiURL)
.pipe(
catchError(this.errorHandler)
)
}
create(person): Observable<Person> {
return this.httpClient.post<Person>(this.apiURL, JSON.stringify(person), this.httpOptions)
.pipe(
catchError(this.errorHandler)
)
}
find(id): Observable<Person> {
return this.httpClient.get<Person>(this.apiURL + id)
.pipe(
catchError(this.errorHandler)
)
}
update(id, person): Observable<Person> {
return this.httpClient.put<Person>(this.apiURL + id, JSON.stringify(person), this.httpOptions)
.pipe(
catchError(this.errorHandler)
)
}
delete(id){
return this.httpClient.delete<Person>(this.apiURL + id, this.httpOptions)
.pipe(
catchError(this.errorHandler)
)
}
errorHandler(error) {
let errorMessage = '';
if(error.error instanceof ErrorEvent) {
errorMessage = error.error.message;
} else {
errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
}
return throwError(errorMessage);
}
}
8 – Components / Componentes
Component Index
src/app/person/index/index.component.ts
import { Component, OnInit } from '@angular/core';
import { PersonService } from '../person.service';
import { Person } from '../person';
@Component({
selector: 'app-index',
templateUrl: './index.component.html',
styleUrls: ['./index.component.css']
})
export class IndexComponent implements OnInit {
persons: Person[] = [];
// constructor() { }
constructor(public personService: PersonService) { }
ngOnInit(): void {
this.personService.getAll().subscribe((data: Person[])=>{
this.persons = data;
console.log(this.persons);
})
}
deletePerson(id){
this.personService.delete(id).subscribe(res => {
this.persons = this.persons.filter(item => item.id !== id);
console.log('Person deleted successfully!');
})
}
}
src/app/person/index/index.component.html
<section>
<div class="d-flex justify-content-between">
<h4>List person</h4>
<a routerLink="/person/create" class="btn btn-success">Create New Person</a>
</div>
<br>
<table class="table ">
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th width="220px">Action</th>
</tr>
<tr *ngFor="let person of persons">
<td>{{ person.id }}</td>
<td>{{ person.name }}</td>
<td>{{ person.email }}</td>
<td>{{ person.phone }}</td>
<td>
<a href="#" [routerLink]="['/person/', 'edit', person.id ]" class="btn btn-primary">Edit</a>
<button type="button" (click)="deletePerson(person.id)" class="btn btn-danger">Delete</button>
</td>
</tr>
</table>
</section>
Component Create
src/app/person/create/create.component.ts
import { Component, OnInit } from '@angular/core';
import { PersonService } from '../person.service';
import { Router } from '@angular/router';
import { FormGroup, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-create',
templateUrl: './create.component.html',
styleUrls: ['./create.component.css']
})
export class CreateComponent implements OnInit {
form: FormGroup;
constructor(
public personService: PersonService,
private router: Router
) { }
ngOnInit(): void {
this.form = new FormGroup({
name: new FormControl('', [ Validators.required, Validators.pattern('^[a-zA-ZÁáÀàÉéÈèÍíÌìÓóÒòÚúÙùÑñüÜ \-\']+') ]),
email: new FormControl('', [ Validators.required, Validators.email ]),
phone: new FormControl('', [ Validators.required, Validators.pattern("^[0-9]*$") ])
});
}
get f(){
return this.form.controls;
}
submit(){
console.log(this.form.value);
this.personService.create(this.form.value).subscribe(res => {
console.log('Person created successfully!');
this.router.navigateByUrl('person/index');
})
}
}
src/app/person/create/create.component.html
<div>
<div class="d-flex justify-content-between">
<h4>Form customer</h4>
<a href="#" routerLink="/person/index" class="btn btn-primaryt">Back</a>
</div>
<hr/>
<form [formGroup]="form" (ngSubmit)="submit()">
<div class="form-group row">
<div class="col-md-6 ">
<label for="title">Name:</label>
<input
formControlName="name"
id="name"
type="text"
class="form-control">
<div *ngIf="f.name.touched && f.name.invalid" class="alert alert-danger">
<div *ngIf="f.name.errors.required">*Name is required.</div>
<div *ngIf="f.name.errors.pattern">*The name must only contain letters.</div>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-md-6 ">
<label for="email">Email:</label>
<input
formControlName="email"
id="email"
type="text"
class="form-control">
<div *ngIf="f.email.touched && f.email.invalid" class="alert alert-danger">
<div *ngIf="f.email.errors.required">*Email is required.</div>
<div *ngIf="f.email.errors.email">*The email must be a valid email address.</div>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-md-6 ">
<label for="phone">Phone:</label>
<input
formControlName="phone"
id="phone"
type="text"
class="form-control">
<div *ngIf="f.phone.touched && f.phone.invalid" class="alert alert-danger">
<div *ngIf="f.phone.errors.required">*Phone is required.</div>
<div *ngIf="f.phone.errors.pattern">*The phone must only contain numbers.</div>
</div>
</div>
</div>
<button class="btn btn-primary" type="submit" [disabled]="!form.valid">Submit</button>
</form>
</div>
Component Edit
src/app/person/edit/edit.component.ts
import { Component, OnInit } from '@angular/core';
import { PersonService } from '../person.service';
import { ActivatedRoute, Router } from '@angular/router';
import { FormGroup, FormControl, Validators} from '@angular/forms';
import { Person } from '../person';
@Component({
selector: 'app-edit',
templateUrl: './edit.component.html',
styleUrls: ['./edit.component.css']
})
export class EditComponent implements OnInit {
id: number;
person: Person;
form: FormGroup;
constructor(
public personService: PersonService,
private route: ActivatedRoute,
private router: Router
) { }
ngOnInit(): void {
this.id = this.route.snapshot.params['idPerson'];
this.personService.find(this.id).subscribe((data: Person)=>{
this.person = data;
});
this.form = new FormGroup({
name: new FormControl('', [ Validators.required, Validators.pattern('^[a-zA-ZÁáÀàÉéÈèÍíÌìÓóÒòÚúÙùÑñüÜ \-\']+') ]),
email: new FormControl('', [ Validators.required, Validators.email ]),
phone: new FormControl('', [ Validators.required, Validators.pattern("^[0-9]*$") ])
});
}
get f(){
return this.form.controls;
}
submit(){
console.log(this.form.value);
this.personService.update(this.id, this.form.value).subscribe(res => {
console.log('Person updated successfully!');
this.router.navigateByUrl('person/index');
})
}
}
src/app/person/edit/edit.component.html
<div class="container">
<div class="d-flex justify-content-between">
<h4>Edit person</h4>
<a href="#" routerLink="/person/index" class="btn btn-primaryt">Back</a>
</div>
<hr>
<form [formGroup]="form" (ngSubmit)="submit()">
<div class="form-group row">
<div class="col-md-6 ">
<label for="title">Name:</label>
<input
formControlName="name"
[(ngModel)]="person.name"
id="name"
type="text"
class="form-control">
<div *ngIf="f.name.touched && f.name.invalid" class="alert alert-danger">
<div *ngIf="f.name.errors.required">*Name is required.</div>
<div *ngIf="f.name.errors.pattern">*The name must only contain letters.</div>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-md-6 ">
<label for="email">Email:</label>
<input
formControlName="email"
[(ngModel)]="person.email"
id="email"
type="text"
class="form-control">
<div *ngIf="f.email.touched && f.email.invalid" class="alert alert-danger">
<div *ngIf="f.email.errors.required">*Email is required.</div>
<div *ngIf="f.email.errors.email">*The email must be a valid email address.</div>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-md-6 ">
<label for="phone">Phone:</label>
<input
[(ngModel)]="person.phone"
formControlName="phone"
id="phone"
type="text"
class="form-control">
<div *ngIf="f.phone.touched && f.phone.invalid" class="alert alert-danger">
<div *ngIf="f.phone.errors.required">*Phone is required.</div>
<div *ngIf="f.phone.errors.pattern">*The phone must only contain numbers.</div>
</div>
</div>
</div>
<button class="btn btn-primary" type="submit" [disabled]="!form.valid">Update</button>
</form>
</div>
9 – Configure person module / Configurar modulo person
src/app/person/person.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { PersonRoutingModule } from './person-routing.module';
import { IndexComponent } from './index/index.component';
import { CreateComponent } from './create/create.component';
import { EditComponent } from './edit/edit.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@NgModule({
declarations: [
IndexComponent,
CreateComponent,
EditComponent
],
imports: [
CommonModule,
PersonRoutingModule,
FormsModule,
ReactiveFormsModule
]
})
export class PersonModule { }
10 – Configure App / Configurar App
src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { PersonModule } from './person/person.module';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
PersonModule,
HttpClientModule,
NgbModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
src/app/app.component.html
<div class="container" style="padding:20px;">
<h1 style="text-align:center;">
<a href="/person/index"> Full Stack - Angular 10 & Laravel 8 </a>
</h1>
<hr>
<main>
<router-outlet></router-outlet>
</main>
</div>
Laravel 8 ( Backend )
1 – Create project / Crear proyecto
composer create-project --prefer-dist laravel/laravel backend
2 – Configure Database / Configurar Base de datos
.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=name_database
DB_USERNAME=user_database
DB_PASSWORD='password_database'
3 – Create migrate / Crear migracion
php artisan make:migration create_person_table
database/migrations/2021_05_17_011217_create_person_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePersonTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('person', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email');
$table->bigInteger('phone');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('person');
}
}
Run migrate / ejecutar migrate
php artisan migrate
4 – Create Model / Crear Modelo
php artisan make:model Person
app/Models/Person.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Person extends Model
{
use HasFactory;
protected $table = "person";
protected $fillable = [
'name',
'email',
'phone'
];
}
5 – Create Controller / Crear Controlador
php artisan make:controller API/PersonController
app/Http/Controllers/API/PersonController.php
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
Use App\Models\Person;
Use Log;
class PersonController extends Controller
{
// https://carbon.now.sh/
public function getAll(){
$data = Person::get();
return response()->json($data, 200);
}
public function create(Request $request){
$data['name'] = $request['name'];
$data['email'] = $request['email'];
$data['phone'] = $request['phone'];
Person::create($data);
return response()->json([
'message' => "Successfully created",
'success' => true
], 200);
}
public function delete($id){
$res = Person::find($id)->delete();
return response()->json([
'message' => "Successfully deleted",
'success' => true
], 200);
}
public function get($id){
$data = Person::find($id);
return response()->json($data, 200);
}
public function update(Request $request,$id){
$data['name'] = $request['name'];
$data['email'] = $request['email'];
$data['phone'] = $request['phone'];
Person::find($id)->update($data);
return response()->json([
'message' => "Successfully updated",
'success' => true
], 200);
}
}
6 – Create routes / Crear rutas
routes/api.php
use App\Http\Controllers\API\PersonController;
Route::prefix('person')->group(function () {
Route::get('/',[ PersonController::class, 'getAll']);
Route::post('/',[ PersonController::class, 'create']);
Route::delete('/{id}',[ PersonController::class, 'delete']);
Route::get('/{id}',[ PersonController::class, 'get']);
Route::put('/{id}',[ PersonController::class, 'update']);
});
GitHub
https://github.com/lucenarenato/angular-10-laravel-8
Fonte:
- https://www.tutofox.com/angular/fullstack-crud-app-angular-10-laravel-8-mysql/
Donate to Site
Renato
Developer