feat(challenge36): add solution on trackby

This commit is contained in:
thomas
2023-10-02 21:42:47 +02:00
parent 0a5bc8514c
commit c062613a8e
30 changed files with 564 additions and 20 deletions

View File

@@ -0,0 +1,58 @@
import { Component, OnInit, inject } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { PersonService } from './list.service';
import { PersonListComponent } from './person-list.component';
@Component({
standalone: true,
imports: [
PersonListComponent,
FormsModule,
MatFormFieldModule,
MatInputModule,
],
providers: [PersonService],
selector: 'app-root',
template: `
<h1 class="font-semibold text-center text-3xl" title="Title">
List of Persons
</h1>
<mat-form-field class="w-3/4">
<input
placeholder="Add one member to the list"
matInput
type="text"
[(ngModel)]="label"
(keydown)="handleKey($event)" />
</mat-form-field>
<app-person-list
class="max-w-2xl w-3/4"
[persons]="persons()"
(delete)="personService.deletePerson($event)"
(update)="personService.updatePerson($event)" />
`,
host: {
class: 'flex items-center flex-col gap-5',
},
})
export class AppComponent implements OnInit {
readonly personService = inject(PersonService);
readonly persons = this.personService.persons;
label = '';
ngOnInit(): void {
this.personService.loadPersons();
}
handleKey(event: any) {
if (event.keyCode === 13) {
this.personService.addPerson(this.label);
this.label = '';
}
}
}

View File

@@ -0,0 +1,6 @@
import { ApplicationConfig } from '@angular/core';
import { provideAnimations } from '@angular/platform-browser/animations';
export const appConfig: ApplicationConfig = {
providers: [provideAnimations()],
};

View File

@@ -0,0 +1,15 @@
import { randEmail, randFirstName } from '@ngneat/falso';
import { Person } from './person.model';
export function generateList() {
const arr: Person[] = [];
for (let i = 0; i < 50; i++) {
arr.push({
email: randEmail(),
name: randFirstName(),
});
}
return arr;
}

View File

@@ -0,0 +1,44 @@
import { Injectable, inject, signal } from '@angular/core';
import { randEmail, randFirstName } from '@ngneat/falso';
import { generateList } from './generateList';
import { Person } from './person.model';
@Injectable()
export class PersonService {
private readonly fakeBackend = inject(FakeBackendService);
readonly persons = signal<Person[]>([]);
loadPersons() {
this.persons.set(generateList());
}
deletePerson(email: string) {
this.persons.set(
this.fakeBackend
.returnNewList(this.persons())
.filter((p) => p.email !== email)
);
}
updatePerson(email: string) {
this.persons.set(
this.fakeBackend
.returnNewList(this.persons())
.map((p) => (p.email === email ? { email, name: randFirstName() } : p))
);
}
addPerson(name: string) {
this.persons.set([
{ email: randEmail(), name },
...this.fakeBackend.returnNewList(this.persons()),
]);
}
}
@Injectable({ providedIn: 'root' })
export class FakeBackendService {
returnNewList = (input: Person[]): Person[] => [
...input.map((i) => ({ ...i })),
];
}

View File

@@ -0,0 +1,37 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Person } from './person.model';
@Component({
selector: 'app-person-list',
standalone: true,
imports: [CommonModule],
template: `
<div
*ngFor="let person of persons"
class="flex justify-between items-center border-b">
<h3>{{ person.name }}</h3>
<div class="flex gap-10 py-1">
<button
class="border rounded-md p-2 bg-blue-500 text-white"
(click)="update.emit(person.email)">
UPDATE
</button>
<button
class="border rounded-md p-2 bg-red-500 text-white"
(click)="delete.emit(person.email)">
DELETE
</button>
</div>
</div>
`,
host: {
class: 'w-full flex flex-col',
},
})
export class PersonListComponent {
@Input() persons: Person[] = [];
@Output() delete = new EventEmitter<string>();
@Output() update = new EventEmitter<string>();
}

View File

@@ -0,0 +1,4 @@
export interface Person {
email: string;
name: string;
}