Skip to content

Commit 45a4366

Browse files
Crud => Update
1 parent 6db3745 commit 45a4366

28 files changed

+6991
-107
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.angular
2+
node_modules

src/app/app.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {HttpClientModule} from "@angular/common/http";
66
@Component({
77
selector: 'app-root',
88
standalone: true,
9-
imports: [RouterOutlet, AsyncPipe, HttpClientModule, CommonModule],
9+
imports: [RouterOutlet, AsyncPipe, HttpClientModule],
1010
templateUrl: './app.component.html',
1111
styleUrl: './app.component.css'
1212
})

src/app/app.config.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import {provideRouter} from '@angular/router';
33
import reducer from "./store/reducer/index";
44
import {routes} from './app.routes';
55
import {provideClientHydration} from '@angular/platform-browser';
6-
import { provideStore} from '@ngrx/store';
6+
import {provideState, provideStore} from '@ngrx/store';
77
import {provideStoreDevtools} from '@ngrx/store-devtools';
88
import {provideHttpClient, withFetch} from "@angular/common/http";
9+
import {updateReducer} from "./store/reducer/update.reducer";
10+
import {showReducer} from "./store/reducer/show.reducer";
911

1012
export const appConfig: ApplicationConfig = {
1113
providers: [
@@ -15,9 +17,6 @@ export const appConfig: ApplicationConfig = {
1517
provideStore(
1618
reducer
1719
),
18-
provideStoreDevtools({
19-
maxAge: 25,
20-
logOnly: !isDevMode()
21-
})
20+
provideStoreDevtools()
2221
]
2322
};

src/app/app.routes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const routes: Routes = [
1414
component: ShowComponent,
1515
},
1616
{
17-
path: 'heroes/edit/:id',
17+
path: 'heroes/:id/edit',
1818
component: EditComponent
1919
},
2020
{
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<button
22
(click)="delete()"
3-
class="px-6 py-2 bg-red-600 text-white text-xs rounded shadow-md hover:bg-red-700">
3+
class="px-6 py-2 bg-red-600 text-white text-xs rounded shadow-md hover:bg-red-700" [disabled]="!id">
44
Delete
55
</button>

src/app/components/common/delete/delete.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Component, Input, Output} from '@angular/core';
1+
import {Component, Input} from '@angular/core';
22
import {HeroService} from "../../../service/hero.service";
33
import {Location} from "@angular/common";
44

@@ -9,7 +9,7 @@ import {Location} from "@angular/common";
99
templateUrl: './delete.component.html',
1010
})
1111
export class DeleteComponent {
12-
@Input() id: string = '';
12+
@Input() id: string | undefined;
1313

1414
constructor(
1515
private heroService: HeroService,
@@ -18,7 +18,7 @@ export class DeleteComponent {
1818
}
1919

2020
delete() {
21-
console.log('delete component id',this.id)
21+
this.id &&
2222
this.heroService.delete(this.id).subscribe(() => this.location.back())
2323
}
2424
}

src/app/components/common/table/table.component.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
<th [colSpan]="2"></th>
1010
</tr>
1111
</thead>
12-
<tbody>
13-
@for (item of items?.items; track item) {
12+
<tbody>
13+
@for (item of items; track item) {
1414
<tr>
1515
<td>{{ item['id'] }}</td>
1616
<td>{{ item['name'] }}</td>
@@ -33,7 +33,7 @@
3333
</a>
3434
</td>
3535
<td class="w-8">
36-
<a [routerLink]="['edit', item['id']]" class="text-cyan-500">
36+
<a [routerLink]="[item['id'], 'edit']" class="text-cyan-500">
3737
Edit
3838
<svg
3939
xmlns="http://www.w3.org/2000/svg"

src/app/components/common/table/table.component.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import {Component, Input} from '@angular/core';
1+
import {Component, Input, WritableSignal} from '@angular/core';
22
import {NgForOf} from "@angular/common";
33
import {RouterLink} from "@angular/router";
44
import {List} from "../../../interface/list.model";
5+
import {Hero} from "../../../interface/hero.model";
6+
import {Observable} from "rxjs";
57

68
@Component({
79
selector: 'app-table',
@@ -12,5 +14,5 @@ import {List} from "../../../interface/list.model";
1214
templateUrl: './table.component.html',
1315
})
1416
export class TableComponent {
15-
@Input() items: List | undefined
17+
@Input() items: Hero[] = [];
1618
}
Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,34 @@
1-
<p>edit works!</p>
1+
<div class="container mx-auto px-4 max-w-2xl mt-4">
2+
3+
<div class="flex items-center justify-between">
4+
<a [routerLink]="['/heroes']"
5+
class="text-blue-600 hover:text-blue-800">
6+
Back to list
7+
</a>
8+
<app-delete [id]="item()?.['@id']"></app-delete>
9+
</div>
10+
@if (isLoading()) {
11+
<div class="bg-blue-100 rounded py-4 px-4 text-blue-700 text-sm">Loading ...</div>
12+
} @else {
13+
<h1 class="text-3xl my-4">Edit {{getItemName()}} {{ item()?.["@id"] }}</h1>
14+
15+
<form (ngSubmit)="onSubmit($event)">
16+
<div class="mb-3">
17+
<label for="name"> name</label>
18+
<input id="name"
19+
class="mt-1 w-full px-3 py-2 border rounded"
20+
[ngModel]="item()?.name"
21+
(ngModelChange)="getItemId($event)"
22+
[ngModelOptions]="{standalone: true}"
23+
>
24+
</div>
25+
26+
<button
27+
type="submit"
28+
class="px-6 py-2 bg-green-500 text-white font-medium rounded shadow-md hover:bg-green-600"
29+
>
30+
Submit
31+
</button>
32+
</form>
33+
}
34+
</div>
Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,84 @@
1-
import { Component } from '@angular/core';
1+
import {Component, computed, effect, OnInit, signal, WritableSignal} from '@angular/core';
2+
import {DeleteComponent} from "../../common/delete/delete.component";
3+
import {Router, RouterLink} from "@angular/router";
4+
import {HeroService} from "../../../service/hero.service";
5+
import {CommonModule, Location} from "@angular/common";
6+
import {ApiShow} from "../../../interface/api";
7+
import {FormBuilder, FormControl, FormsModule, ReactiveFormsModule} from "@angular/forms";
8+
29

310
@Component({
411
selector: 'app-edit',
512
standalone: true,
6-
imports: [],
13+
imports: [
14+
CommonModule,
15+
DeleteComponent,
16+
RouterLink,
17+
FormsModule,
18+
ReactiveFormsModule,
19+
],
720
templateUrl: './edit.component.html',
821
})
9-
export class EditComponent {
22+
export class EditComponent implements OnInit {
23+
public isLoading: WritableSignal<boolean> = signal(false)
24+
public item: WritableSignal<ApiShow | null> = signal(null)
25+
public reactiveInputName = new FormControl(this.item()?.name, {nonNullable: true})
26+
27+
constructor(
28+
private router: Router,
29+
private heroService: HeroService,
30+
private formBuilder: FormBuilder,
31+
private location: Location
32+
) {
33+
effect(() => {
34+
console.log('item change ==>', this.item())
35+
});
36+
}
37+
38+
ngOnInit() {
39+
this.loadData()
40+
}
41+
42+
loadData() {
43+
this.isLoading.set(true)
44+
const splitUrl = this.router.url.split('/edit')[0]
45+
this.heroService
46+
.getHero(splitUrl)
47+
.subscribe(item => {
48+
this.item.set(item)
49+
this.isLoading.set(false)
50+
})
51+
}
52+
53+
getItemName() {
54+
return computed(() => this.item()?.name)
55+
}
56+
57+
getItemId(event: any) {
58+
this.item.update(update => {
59+
if (update) {
60+
return {
61+
...update,
62+
name: event
63+
}
64+
} else {
65+
return update
66+
}
67+
})
68+
}
69+
70+
getItemComputed() {
71+
return computed(() => this.item())
72+
}
73+
74+
onSubmit(event: any) {
75+
return this.heroService.putHero(
76+
this.item()?.["@id"],
77+
this.item()
78+
) .subscribe( () => {
79+
this.location.back()
80+
})
81+
}
1082

83+
protected readonly name = name;
1184
}

src/app/components/foo/list/list.component.html

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ <h1 class="text-3xl mb-2">Heroes List</h1>
77
Create
88
</a>
99
</div>
10-
<p *ngIf="(isLoading | async) else tableHeroes">Loading ... </p>
11-
<ng-template #tableHeroes>
12-
<app-table [items]="(heroes$ | async)!"></app-table>
13-
</ng-template>
10+
@if (isLoading()) {
11+
<div class="bg-blue-100 rounded py-4 px-4 text-blue-700 text-sm">Loading ... </div>
12+
} @else {
13+
<app-table [items]="heroes()"></app-table>
14+
}
1415
</div>
Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
import {Component, OnInit} from '@angular/core';
1+
import {Component, OnInit, signal, WritableSignal} from '@angular/core';
22
import {RouterLink} from "@angular/router";
33
import {AsyncPipe, NgFor, NgIf} from "@angular/common";
44
import {TableComponent} from "../../common/table/table.component";
5-
import {List} from "../../../interface/list.model";
6-
import {Store} from "@ngrx/store";
7-
import {HeroesActions} from "../../../store/action/heroes.actions";
85
import {HeroService} from "../../../service/hero.service";
9-
import {selectorHeroesLoading} from "../../../store/selector/hero.selectors";
6+
import {Hero} from "../../../interface/hero.model";
107

118
@Component({
129
selector: 'app-list',
@@ -21,21 +18,23 @@ import {selectorHeroesLoading} from "../../../store/selector/hero.selectors";
2118
templateUrl: './list.component.html',
2219
})
2320
export class ListComponent implements OnInit {
24-
heroes$ = this.store.select('heroes')
25-
isLoading = this.store.select(selectorHeroesLoading)
21+
heroes: WritableSignal<Hero[] | []> = signal([])
22+
isLoading = signal(false)
23+
error = signal(undefined)
2624

27-
constructor(private store: Store<{ heroes: List }>, private heroService: HeroService) {
25+
constructor(
26+
private heroService: HeroService,
27+
) {
2828
}
2929

3030
ngOnInit() {
31+
this.isLoading.set(true)
3132
this.heroService
3233
.getHeroes('/heroes')
3334
.subscribe(
34-
(items) =>
35-
this.store.dispatch(HeroesActions.getHeroes({
36-
items: items['hydra:member'],
37-
isLoading: false
38-
}))
39-
)
35+
(items) => {
36+
this.heroes.set(items['hydra:member'])
37+
this.isLoading.set(false)
38+
})
4039
}
4140
}
Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
<div class="container mx-auto px-4 max-w-2xl mt-4">
2-
<p *ngIf="(isLoading | async) else elseData">Loading ... </p>
3-
<ng-template #elseData>
2+
@if (isLoading()) {
3+
<div class="bg-blue-100 rounded py-4 px-4 text-blue-700 text-sm">Loading ...</div>
4+
} @else {
45
<div class="flex items-center justify-between">
56
<a [routerLink]="['/heroes']"
67
class="text-blue-600 hover:text-blue-800">
78
Back to list
89
</a>
910
<div>
10-
<a [routerLink]="['/heroes/edit', (item|async)?.id]"
11+
<a [routerLink]="[item()?.['@id'], 'edit']"
1112
class="px-6 py-2 mr-2 bg-green-600 text-white text-xs rounded shadow-md hover:bg-green-700">
1213
Edit
1314
</a>
14-
<app-delete [id]="(item|async)?.['@id']!"></app-delete>
15+
<app-delete [id]="item()?.['@id']"></app-delete>
1516
</div>
1617
</div>
1718

18-
<h1 class="text-3xl my-4">Show {{ (item|async)?.["@id"] }}</h1>
19+
<h1 class="text-3xl my-4">Show {{ item()?.['@id'] }}</h1>
1920

2021
<div class="overflow-x-auto">
2122
<table class="min-w-full">
@@ -30,19 +31,21 @@ <h1 class="text-3xl my-4">Show {{ (item|async)?.["@id"] }}</h1>
3031
</tr>
3132
</thead>
3233
<tbody>
33-
<tr *ngIf="(item | async)" class="border-b">
34-
<th
35-
class="text-sm font-medium px-6 py-4 text-left capitalize"
36-
scope="row"
37-
>
38-
name
39-
</th>
40-
<td class="px-6 py-4 whitespace-nowrap text-sm">
41-
{{ (item|async)?.name }}
42-
</td>
43-
</tr>
34+
@if (item()) {
35+
<tr class="border-b">
36+
<th
37+
class="text-sm font-medium px-6 py-4 text-left capitalize"
38+
scope="row"
39+
>
40+
name
41+
</th>
42+
<td class="px-6 py-4 whitespace-nowrap text-sm">
43+
{{ item()?.name }}
44+
</td>
45+
</tr>
46+
}
4447
</tbody>
4548
</table>
4649
</div>
47-
</ng-template>
50+
}
4851
</div>

0 commit comments

Comments
 (0)