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
Solución de error
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']); });
Excelente publicación, una pregunta, ¿Que cambiaría si fuera con mariadb? Saludos
Si claro