@one-paragon/angular-utilities 2.8.4 → 2.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/one-paragon-angular-utilities.mjs +7350 -0
- package/fesm2022/one-paragon-angular-utilities.mjs.map +1 -0
- package/package.json +27 -15
- package/types/one-paragon-angular-utilities.d.ts +2211 -0
- package/karma.conf.js +0 -43
- package/ng-package.json +0 -7
- package/src/action-state/action-state-spinner/action-state-spinner.component.css +0 -16
- package/src/action-state/action-state-spinner/action-state-spinner.component.html +0 -7
- package/src/action-state/action-state-spinner/action-state-spinner.component.spec.ts +0 -25
- package/src/action-state/action-state-spinner/action-state-spinner.component.ts +0 -26
- package/src/action-state/action-state-ui/action-state-ui.module.ts +0 -13
- package/src/action-state/index.ts +0 -8
- package/src/action-state/ngrx-ext/ngrx-ext.module.ts +0 -14
- package/src/action-state/ngrx.ts +0 -69
- package/src/http-request-state/RequestStateFactory.ts +0 -56
- package/src/http-request-state/RequestStateStore.ts +0 -360
- package/src/http-request-state/deprecated.ts +0 -20
- package/src/http-request-state/directives/HttpStateDirectiveBase.ts +0 -29
- package/src/http-request-state/directives/http-error-state-directive.ts +0 -21
- package/src/http-request-state/directives/http-inProgress-state-directive.ts +0 -19
- package/src/http-request-state/directives/http-notStarted-state-directive.ts +0 -19
- package/src/http-request-state/directives/http-success-state-directive.ts +0 -29
- package/src/http-request-state/directives/index.ts +0 -5
- package/src/http-request-state/directives/request-state-directive.spec.ts +0 -73
- package/src/http-request-state/directives/request-state-directive.ts +0 -78
- package/src/http-request-state/documentation/CREATE-REQUESTOR.md +0 -667
- package/src/http-request-state/documentation/README.md +0 -191
- package/src/http-request-state/documentation/REQUEST-STATE-STORE-CONFIG.md +0 -648
- package/src/http-request-state/documentation/REQUESTOR.md +0 -616
- package/src/http-request-state/helpers.ts +0 -30
- package/src/http-request-state/http-state-module.ts +0 -23
- package/src/http-request-state/index.ts +0 -7
- package/src/http-request-state/models/view-context.ts +0 -18
- package/src/http-request-state/observable.spec.ts +0 -43
- package/src/http-request-state/request-state.ts +0 -66
- package/src/http-request-state/rxjs/getRequestorBody.ts +0 -10
- package/src/http-request-state/rxjs/getRequestorState.ts +0 -8
- package/src/http-request-state/rxjs/index.ts +0 -4
- package/src/http-request-state/rxjs/tapError.ts +0 -16
- package/src/http-request-state/rxjs/tapSuccess.ts +0 -16
- package/src/http-request-state/strategies.spec.ts +0 -42
- package/src/http-request-state/types.ts +0 -54
- package/src/ngrx/actionable-selector.ts +0 -189
- package/src/ngrx/index.ts +0 -1
- package/src/public-api.ts +0 -40
- package/src/rxjs/defaultShareReplay.ts +0 -8
- package/src/rxjs/index.ts +0 -5
- package/src/rxjs/mapError.ts +0 -8
- package/src/rxjs/rxjs-operators.ts +0 -130
- package/src/rxjs/subjectifier.ts +0 -17
- package/src/rxjs/subscriber.directive.ts +0 -57
- package/src/specs/clickSubject.spec.ts +0 -99
- package/src/specs/dialog.spec.ts +0 -101
- package/src/specs/toggleGroupDirective.spec.ts +0 -229
- package/src/table-builder/classes/DefaultSettings.ts +0 -11
- package/src/table-builder/classes/MatTableObservableDataSource.ts +0 -23
- package/src/table-builder/classes/TableBuilderConfig.ts +0 -49
- package/src/table-builder/classes/TableBuilderDataSource.ts +0 -64
- package/src/table-builder/classes/TableState.ts +0 -96
- package/src/table-builder/classes/data-store.ts +0 -10
- package/src/table-builder/classes/display-col.ts +0 -5
- package/src/table-builder/classes/filter-info.ts +0 -129
- package/src/table-builder/classes/table-builder-general-settings.ts +0 -233
- package/src/table-builder/classes/table-builder.ts +0 -105
- package/src/table-builder/classes/table-store.helpers.ts +0 -109
- package/src/table-builder/classes/table-store.ts +0 -540
- package/src/table-builder/components/array-column.component.ts +0 -34
- package/src/table-builder/components/column-builder/column-builder.component.html +0 -109
- package/src/table-builder/components/column-builder/column-builder.component.scss +0 -43
- package/src/table-builder/components/column-builder/column-builder.component.spec.ts +0 -49
- package/src/table-builder/components/column-builder/column-builder.component.ts +0 -130
- package/src/table-builder/components/column-builder/column-helpers.ts +0 -54
- package/src/table-builder/components/column-header-menu/column-header-menu.component.html +0 -128
- package/src/table-builder/components/column-header-menu/column-header-menu.component.scss +0 -97
- package/src/table-builder/components/column-header-menu/column-header-menu.component.ts +0 -113
- package/src/table-builder/components/date-filter/date-filter.component.html +0 -39
- package/src/table-builder/components/date-filter/date-filter.component.ts +0 -33
- package/src/table-builder/components/date-time-filter/date-time-filter.component.html +0 -25
- package/src/table-builder/components/date-time-filter/date-time-filter.component.ts +0 -33
- package/src/table-builder/components/filter/filter.component.html +0 -120
- package/src/table-builder/components/filter/filter.component.scss +0 -60
- package/src/table-builder/components/filter/filter.component.spec.ts +0 -86
- package/src/table-builder/components/filter/filter.component.ts +0 -73
- package/src/table-builder/components/filter/in-list/in-list-filter.component.ts +0 -171
- package/src/table-builder/components/gen-col-displayer/gen-col-displayer.component.html +0 -60
- package/src/table-builder/components/gen-col-displayer/gen-col-displayer.component.scss +0 -57
- package/src/table-builder/components/gen-col-displayer/gen-col-displayer.component.ts +0 -44
- package/src/table-builder/components/generic-table/generic-table.component.html +0 -140
- package/src/table-builder/components/generic-table/generic-table.component.scss +0 -45
- package/src/table-builder/components/generic-table/generic-table.component.ts +0 -531
- package/src/table-builder/components/generic-table/paginator.component.ts +0 -125
- package/src/table-builder/components/group-by-list/group-by-list.component.css +0 -24
- package/src/table-builder/components/group-by-list/group-by-list.component.html +0 -21
- package/src/table-builder/components/group-by-list/group-by-list.component.spec.ts +0 -23
- package/src/table-builder/components/group-by-list/group-by-list.component.ts +0 -26
- package/src/table-builder/components/in-filter/in-filter.component.css +0 -22
- package/src/table-builder/components/in-filter/in-filter.component.html +0 -38
- package/src/table-builder/components/in-filter/in-filter.component.ts +0 -66
- package/src/table-builder/components/index.ts +0 -9
- package/src/table-builder/components/initialization-component/initialization.component.html +0 -78
- package/src/table-builder/components/initialization-component/initialization.component.ts +0 -28
- package/src/table-builder/components/link-column.component.ts +0 -42
- package/src/table-builder/components/number-filter/number-filter.component.css +0 -10
- package/src/table-builder/components/number-filter/number-filter.component.html +0 -32
- package/src/table-builder/components/number-filter/number-filter.component.spec.ts +0 -30
- package/src/table-builder/components/number-filter/number-filter.component.ts +0 -34
- package/src/table-builder/components/profiles-menu/profiles-menu.component.html +0 -77
- package/src/table-builder/components/profiles-menu/profiles-menu.component.scss +0 -126
- package/src/table-builder/components/profiles-menu/profiles-menu.component.spec.ts +0 -23
- package/src/table-builder/components/profiles-menu/profiles-menu.component.ts +0 -64
- package/src/table-builder/components/reset-menu/reset-menu.component.css +0 -3
- package/src/table-builder/components/reset-menu/reset-menu.component.html +0 -10
- package/src/table-builder/components/reset-menu/reset-menu.component.ts +0 -87
- package/src/table-builder/components/scroll-strategy.ts +0 -139
- package/src/table-builder/components/sort-menu/sort-menu.component-store.ts +0 -57
- package/src/table-builder/components/sort-menu/sort-menu.component.html +0 -115
- package/src/table-builder/components/sort-menu/sort-menu.component.scss +0 -119
- package/src/table-builder/components/sort-menu/sort-menu.component.ts +0 -88
- package/src/table-builder/components/table-container/table-container.component.html +0 -94
- package/src/table-builder/components/table-container/table-container.component.scss +0 -60
- package/src/table-builder/components/table-container/table-container.component.ts +0 -467
- package/src/table-builder/components/table-container/table-container.helpers/data-state.helpers.ts +0 -113
- package/src/table-builder/components/table-container/table-container.helpers/filter-state.helpers.ts +0 -125
- package/src/table-builder/components/table-container/table-container.helpers/groupBy.helpers.ts +0 -172
- package/src/table-builder/components/table-container/table-container.helpers/meta-data.helpers.ts +0 -19
- package/src/table-builder/components/table-container/table-container.helpers/sort-state.helpers.ts +0 -47
- package/src/table-builder/components/table-container/tableProps.ts +0 -21
- package/src/table-builder/components/table-container/virtual-scroll-container.ts +0 -216
- package/src/table-builder/components/table-container-filter/filter-list/filter-list.component.html +0 -42
- package/src/table-builder/components/table-container-filter/filter-list/filter-list.component.ts +0 -47
- package/src/table-builder/components/table-container-filter/gen-filter-displayer/gen-filter-displayer.component.css +0 -40
- package/src/table-builder/components/table-container-filter/gen-filter-displayer/gen-filter-displayer.component.html +0 -11
- package/src/table-builder/components/table-container-filter/gen-filter-displayer/gen-filter-displayer.component.spec.ts +0 -85
- package/src/table-builder/components/table-container-filter/gen-filter-displayer/gen-filter-displayer.component.ts +0 -35
- package/src/table-builder/components/table-container-filter/table-wrapper-filter-store.ts +0 -13
- package/src/table-builder/components/table-header-menu/table-header-menu.component.css +0 -21
- package/src/table-builder/components/table-header-menu/table-header-menu.component.html +0 -48
- package/src/table-builder/components/table-header-menu/table-header-menu.component.ts +0 -36
- package/src/table-builder/directives/custom-cell-directive.ts +0 -63
- package/src/table-builder/directives/custom-header-directive.ts +0 -16
- package/src/table-builder/directives/group-row-directive.ts +0 -91
- package/src/table-builder/directives/index.ts +0 -8
- package/src/table-builder/directives/multi-sort.directive.spec.ts +0 -124
- package/src/table-builder/directives/multi-sort.directive.ts +0 -58
- package/src/table-builder/directives/resize-column.directive.ts +0 -107
- package/src/table-builder/directives/table-wrapper.directive.ts +0 -13
- package/src/table-builder/directives/tb-filter.directive.ts +0 -376
- package/src/table-builder/documentation/table-builder/CUSTOM-CELL.md +0 -568
- package/src/table-builder/documentation/table-builder/CUSTOM-GROUP-ROW.md +0 -356
- package/src/table-builder/documentation/table-builder/METADATA-DOCUMENTATION.md +0 -517
- package/src/table-builder/documentation/table-builder/STYLER-STYLE.md +0 -228
- package/src/table-builder/documentation/table-builder/TABLE-BUILDER-CONFIG.md +0 -325
- package/src/table-builder/documentation/table-builder/TABLE-BUILDER-SETTINGS.md +0 -515
- package/src/table-builder/documentation/table-builder/TABLE-BUILDER.md +0 -430
- package/src/table-builder/documentation/table-builder/TABLE-CONTAINER.md +0 -628
- package/src/table-builder/enums/filterTypes.ts +0 -39
- package/src/table-builder/functions/boolean-filter-function.ts +0 -12
- package/src/table-builder/functions/date-filter-function.ts +0 -85
- package/src/table-builder/functions/download-data.ts +0 -11
- package/src/table-builder/functions/null-filter-function.ts +0 -9
- package/src/table-builder/functions/number-filter-function.ts +0 -47
- package/src/table-builder/functions/sort-data-function.ts +0 -80
- package/src/table-builder/functions/string-filter-function.ts +0 -59
- package/src/table-builder/interfaces/ColumnInfo.ts +0 -9
- package/src/table-builder/interfaces/dictionary.ts +0 -3
- package/src/table-builder/interfaces/meta-data.ts +0 -279
- package/src/table-builder/ngrx/tableBuilderStateStore.ts +0 -203
- package/src/table-builder/pipes/column-total.pipe.ts +0 -16
- package/src/table-builder/pipes/format-filter-type.pipe.ts +0 -12
- package/src/table-builder/pipes/format-filter-value.pipe.ts +0 -71
- package/src/table-builder/pipes/key-display.ts +0 -13
- package/src/table-builder/services/all-values-filter-creator.service.ts +0 -92
- package/src/table-builder/services/export-to-csv.service.ts +0 -117
- package/src/table-builder/services/link-creator.service.ts +0 -98
- package/src/table-builder/services/table-template-service.ts +0 -47
- package/src/table-builder/services/transform-creator.ts +0 -90
- package/src/table-builder/specs/table-custom-filters.spec.ts +0 -262
- package/src/table-builder/styles/collapser.styles.scss +0 -16
- package/src/table-builder/table-builder.module.ts +0 -42
- package/src/table-builder/types/group-types.ts +0 -42
- package/src/table-builder/types/index.ts +0 -1
- package/src/test.ts +0 -17
- package/src/utilities/array-helpers.ts +0 -13
- package/src/utilities/directives/auto-focus.directive.ts +0 -20
- package/src/utilities/directives/clickEmitterDirective.ts +0 -15
- package/src/utilities/directives/clickSubject.ts +0 -19
- package/src/utilities/directives/conditional-classes.directive.ts +0 -36
- package/src/utilities/directives/dialog-service.ts +0 -19
- package/src/utilities/directives/dialog.ts +0 -174
- package/src/utilities/directives/mat-toggle-group-directive.ts +0 -60
- package/src/utilities/directives/prevent-enter.directive.ts +0 -12
- package/src/utilities/directives/stop-propagation.directive.ts +0 -19
- package/src/utilities/directives/styler.ts +0 -45
- package/src/utilities/directives/trim-whitespace.directive.ts +0 -20
- package/src/utilities/index.ts +0 -22
- package/src/utilities/module.ts +0 -53
- package/src/utilities/pipes/function.pipe.ts +0 -21
- package/src/utilities/pipes/phone.pipe.ts +0 -20
- package/src/utilities/pipes/space-case.pipes.spec.ts +0 -47
- package/src/utilities/pipes/space-case.pipes.ts +0 -29
- package/tsconfig.lib.json +0 -20
- package/tsconfig.lib.prod.json +0 -10
- package/tsconfig.spec.json +0 -17
|
@@ -1,616 +0,0 @@
|
|
|
1
|
-
# Requestor (RequestStateStore) Documentation
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
The `RequestStateStore` class (commonly referred to as a "Requestor") is a powerful state management solution for handling HTTP requests and their associated states in Angular applications. It provides a signal-based reactive approach to managing request states, handling errors and successes, and coordinating multiple concurrent requests.
|
|
6
|
-
|
|
7
|
-
## Key Features
|
|
8
|
-
|
|
9
|
-
- **Signal-based State Management**: Uses Angular signals for reactive state updates
|
|
10
|
-
- **Multiple Request Strategies**: Supports concurrent, sequential, single-use, and cancel-previous patterns
|
|
11
|
-
- **Automatic Lifecycle Management**: Integrates with Angular's `DestroyRef` for automatic cleanup
|
|
12
|
-
- **Flexible Error Handling**: Multiple ways to handle errors with optional default handlers
|
|
13
|
-
- **Success Callbacks**: Various patterns for handling successful responses
|
|
14
|
-
- **Type-safe**: Full TypeScript support with generic type parameters
|
|
15
|
-
- **Observable and Signal Support**: Works seamlessly with both observables and signals
|
|
16
|
-
|
|
17
|
-
## Creating a Requestor
|
|
18
|
-
|
|
19
|
-
### Using `createRequestor` (Recommended)
|
|
20
|
-
|
|
21
|
-
```typescript
|
|
22
|
-
import { createRequestor } from 'angular-utilities';
|
|
23
|
-
import { HttpClient } from '@angular/common/http';
|
|
24
|
-
|
|
25
|
-
// In a component or service
|
|
26
|
-
export class UserService {
|
|
27
|
-
private http = inject(HttpClient);
|
|
28
|
-
|
|
29
|
-
// Simple requestor
|
|
30
|
-
getUserRequestor = createRequestor(
|
|
31
|
-
(userId: number) => this.http.get<User>(`/api/users/${userId}`)
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
// With projection (transforming response)
|
|
35
|
-
getTransformedUserRequestor = createRequestor(
|
|
36
|
-
(userId: number) => this.http.get<UserDTO>(`/api/users/${userId}`),
|
|
37
|
-
(dto) => this.mapToUser(dto) // Projection function
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
// With options
|
|
41
|
-
getMultipleUsersRequestor = createRequestor(
|
|
42
|
-
(userIds: number[]) => this.http.post<User[]>('/api/users/batch', userIds),
|
|
43
|
-
{ strategy: RequestStrategy.concurrent }
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### Using `RequestStateFactory`
|
|
49
|
-
|
|
50
|
-
```typescript
|
|
51
|
-
import { RequestStateFactory } from 'angular-utilities';
|
|
52
|
-
|
|
53
|
-
@Component({
|
|
54
|
-
providers: [RequestStateFactory]
|
|
55
|
-
})
|
|
56
|
-
export class MyComponent {
|
|
57
|
-
private factory = inject(RequestStateFactory);
|
|
58
|
-
private http = inject(HttpClient);
|
|
59
|
-
|
|
60
|
-
getUserRequestor = this.factory.create(
|
|
61
|
-
(userId: number) => this.http.get<User>(`/api/users/${userId}`)
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### Direct Instantiation (Advanced)
|
|
67
|
-
|
|
68
|
-
```typescript
|
|
69
|
-
// Must be in an injection context
|
|
70
|
-
const requestor = new RequestStateStore(
|
|
71
|
-
(userId: number) => this.http.get<User>(`/api/users/${userId}`),
|
|
72
|
-
{ strategy: RequestStrategy.cancelPrevious }
|
|
73
|
-
);
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Type Parameters
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
RequestStateStore<TParam, V, R, T>
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
- **`TParam`**: Array type of parameters accepted by the request function (e.g., `[number, string]`)
|
|
83
|
-
- **`V`**: The raw response type from the request (e.g., `UserDTO`)
|
|
84
|
-
- **`R`**: The projected response type (optional, defaults to `null`)
|
|
85
|
-
- **`T`**: The final type (defaults to `V` if no projection, otherwise `R`)
|
|
86
|
-
|
|
87
|
-
## Request Strategies
|
|
88
|
-
|
|
89
|
-
### `RequestStrategy.cancelPrevious` (Default)
|
|
90
|
-
|
|
91
|
-
Cancels the previous in-flight request when a new request is made (uses RxJS `switchMap`).
|
|
92
|
-
|
|
93
|
-
```typescript
|
|
94
|
-
const requestor = createRequestor(
|
|
95
|
-
(query: string) => this.http.get(`/api/search?q=${query}`),
|
|
96
|
-
{ strategy: RequestStrategy.cancelPrevious }
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
// Only the last request will complete
|
|
100
|
-
requestor.request('first');
|
|
101
|
-
requestor.request('second'); // Cancels 'first'
|
|
102
|
-
requestor.request('third'); // Cancels 'second'
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### `RequestStrategy.concurrent`
|
|
106
|
-
|
|
107
|
-
Allows multiple requests to run simultaneously (uses RxJS `mergeMap`).
|
|
108
|
-
|
|
109
|
-
```typescript
|
|
110
|
-
const requestor = createRequestor(
|
|
111
|
-
(userId: number) => this.http.get(`/api/users/${userId}`),
|
|
112
|
-
{ strategy: RequestStrategy.concurrent }
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
// All three requests will execute
|
|
116
|
-
requestor.request(1);
|
|
117
|
-
requestor.request(2);
|
|
118
|
-
requestor.request(3);
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
### `RequestStrategy.sequential`
|
|
122
|
-
|
|
123
|
-
Queues requests and executes them one at a time (uses RxJS `concatMap`).
|
|
124
|
-
|
|
125
|
-
```typescript
|
|
126
|
-
const requestor = createRequestor(
|
|
127
|
-
(data: FormData) => this.http.post('/api/upload', data),
|
|
128
|
-
{ strategy: RequestStrategy.sequential }
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
// Requests execute in order
|
|
132
|
-
requestor.request(file1); // Executes immediately
|
|
133
|
-
requestor.request(file2); // Waits for file1 to complete
|
|
134
|
-
requestor.request(file3); // Waits for file2 to complete
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
### `RequestStrategy.singleUse`
|
|
138
|
-
|
|
139
|
-
Allows only one request for the lifetime of the requestor. Must call `reset()` before making another request.
|
|
140
|
-
|
|
141
|
-
```typescript
|
|
142
|
-
const requestor = createRequestor(
|
|
143
|
-
() => this.http.post('/api/initialize', {}),
|
|
144
|
-
{ strategy: RequestStrategy.singleUse }
|
|
145
|
-
);
|
|
146
|
-
|
|
147
|
-
requestor.request(); // Works
|
|
148
|
-
requestor.request(); // Throws error!
|
|
149
|
-
|
|
150
|
-
requestor.reset();
|
|
151
|
-
requestor.request(); // Works again
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## State Management
|
|
155
|
-
|
|
156
|
-
### Signal-based State
|
|
157
|
-
|
|
158
|
-
```typescript
|
|
159
|
-
const requestor = createRequestor(
|
|
160
|
-
(id: number) => this.http.get<User>(`/api/users/${id}`)
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
// Access the full state
|
|
164
|
-
const state = requestor.state(); // Signal<RequestResponse<[number], User>>
|
|
165
|
-
|
|
166
|
-
// Access computed signals
|
|
167
|
-
const status = requestor.$selectStatus(); // Signal<RequestStatus>
|
|
168
|
-
const isLoading = requestor.$isInProgress(); // Signal<boolean>
|
|
169
|
-
const isSuccess = requestor.$isSuccess(); // Signal<boolean>
|
|
170
|
-
const isError = requestor.$isError(); // Signal<boolean>
|
|
171
|
-
const response = requestor.$selectResponse(); // Signal<User | undefined>
|
|
172
|
-
const error = requestor.$selectError(); // Signal<HttpErrorResponse | undefined>
|
|
173
|
-
|
|
174
|
-
// Use in templates
|
|
175
|
-
@Component({
|
|
176
|
-
template: `
|
|
177
|
-
@if (userRequestor.$isInProgress()) {
|
|
178
|
-
<app-loading />
|
|
179
|
-
} @else if (userRequestor.$isSuccess()) {
|
|
180
|
-
<app-user-details [user]="userRequestor.$selectResponse()!" />
|
|
181
|
-
} @else if (userRequestor.$isError()) {
|
|
182
|
-
<app-error [error]="userRequestor.$selectError()!" />
|
|
183
|
-
}
|
|
184
|
-
`
|
|
185
|
-
})
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
### Observable-based State
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
const requestor = createRequestor(
|
|
192
|
-
(id: number) => this.http.get<User>(`/api/users/${id}`)
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
// Observable streams
|
|
196
|
-
requestor.state$ // Observable<RequestResponse<[number], User>>
|
|
197
|
-
requestor.selectRequestState$ // Observable<RequestState<User>>
|
|
198
|
-
requestor.selectResponse$ // Observable<User> (only emits on success)
|
|
199
|
-
requestor.selectStatus$ // Observable<RequestStatus>
|
|
200
|
-
requestor.selectError$ // Observable<HttpErrorResponse>
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
## Making Requests
|
|
204
|
-
|
|
205
|
-
### Basic Request
|
|
206
|
-
|
|
207
|
-
```typescript
|
|
208
|
-
const requestor = createRequestor(
|
|
209
|
-
(userId: number) => this.http.get<User>(`/api/users/${userId}`)
|
|
210
|
-
);
|
|
211
|
-
|
|
212
|
-
// Make the request
|
|
213
|
-
requestor.request(123);
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
### Auto Request
|
|
217
|
-
|
|
218
|
-
Automatically make the request when the requestor is created (only works with no-parameter requests).
|
|
219
|
-
|
|
220
|
-
```typescript
|
|
221
|
-
const requestor = createRequestor(
|
|
222
|
-
() => this.http.get<Config>('/api/config'),
|
|
223
|
-
{ autoRequest: true }
|
|
224
|
-
);
|
|
225
|
-
// Request is made immediately
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
### Request With Observable
|
|
229
|
-
|
|
230
|
-
```typescript
|
|
231
|
-
const userId$ = new BehaviorSubject<number>(1);
|
|
232
|
-
|
|
233
|
-
requestor.requestWith(userId$.pipe(map(id => [id])));
|
|
234
|
-
// Makes a request whenever userId$ emits
|
|
235
|
-
// Must map to an array of parameters
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
### Request With Signal
|
|
239
|
-
|
|
240
|
-
```typescript
|
|
241
|
-
const userId = signal(1);
|
|
242
|
-
const userIdArray = computed(() => [userId()]);
|
|
243
|
-
|
|
244
|
-
requestor.requestWith(userIdArray);
|
|
245
|
-
// Makes a request whenever userId changes
|
|
246
|
-
// Must be a signal of an array of parameters
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
### Request On Signal Changes
|
|
250
|
-
|
|
251
|
-
Track multiple signals and make requests when they change.
|
|
252
|
-
|
|
253
|
-
```typescript
|
|
254
|
-
const userId = signal(1);
|
|
255
|
-
const includeDetails = signal(false);
|
|
256
|
-
|
|
257
|
-
requestor.requestOn(userId, includeDetails);
|
|
258
|
-
// Makes a request whenever userId or includeDetails change
|
|
259
|
-
// Skips request if any signal is undefined
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
## Error Handling
|
|
263
|
-
|
|
264
|
-
### Basic Error Handler
|
|
265
|
-
|
|
266
|
-
```typescript
|
|
267
|
-
const requestor = createRequestor(
|
|
268
|
-
(id: number) => this.http.get<User>(`/api/users/${id}`)
|
|
269
|
-
).onError((error: HttpErrorResponse) => {
|
|
270
|
-
console.error('Request failed:', error);
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
requestor.request(123);
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
### Error with Response Parameters
|
|
277
|
-
|
|
278
|
-
```typescript
|
|
279
|
-
requestor.onErrorResponse((error, userId) => {
|
|
280
|
-
console.error(`Failed to load user ${userId}:`, error);
|
|
281
|
-
});
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
### Error with Request Parameters Only
|
|
285
|
-
|
|
286
|
-
```typescript
|
|
287
|
-
requestor.onErrorRequest((userId) => {
|
|
288
|
-
console.log(`Request for user ${userId} failed`);
|
|
289
|
-
});
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
### Error with Full Context
|
|
293
|
-
|
|
294
|
-
```typescript
|
|
295
|
-
requestor.onErrorWithRequest(({ error, requestParams }) => {
|
|
296
|
-
const [userId] = requestParams;
|
|
297
|
-
console.error(`User ${userId} request failed:`, error.message);
|
|
298
|
-
});
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
### Default Error Handler
|
|
302
|
-
|
|
303
|
-
```typescript
|
|
304
|
-
// Use the globally configured error handler
|
|
305
|
-
requestor.useDefaultErrorHandler();
|
|
306
|
-
|
|
307
|
-
// Or configure globally in module/component providers
|
|
308
|
-
{
|
|
309
|
-
provide: RequestStateStoreConfigToken,
|
|
310
|
-
useValue: {
|
|
311
|
-
defaultErrorHandling: (error) => {
|
|
312
|
-
this.toastr.error('Request failed', error.message);
|
|
313
|
-
},
|
|
314
|
-
useDefaultErrorHandler: true // Auto-apply to all requestors
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
**Note:** See [RequestStateStoreConfig Documentation](./REQUEST-STATE-STORE-CONFIG.md) for complete details on configuring global error handlers.
|
|
320
|
-
|
|
321
|
-
## Success Handling
|
|
322
|
-
|
|
323
|
-
### Basic Success Handler
|
|
324
|
-
|
|
325
|
-
```typescript
|
|
326
|
-
const requestor = createRequestor(
|
|
327
|
-
(id: number) => this.http.delete(`/api/users/${id}`)
|
|
328
|
-
).onSuccess(() => {
|
|
329
|
-
console.log('User deleted successfully');
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
requestor.request(123);
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
### Success with Response
|
|
336
|
-
|
|
337
|
-
```typescript
|
|
338
|
-
requestor.onSuccess((user: User) => {
|
|
339
|
-
console.log('Loaded user:', user.name);
|
|
340
|
-
});
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
### Success with Response and Parameters
|
|
344
|
-
|
|
345
|
-
```typescript
|
|
346
|
-
requestor.onSuccessResponse((user, userId) => {
|
|
347
|
-
console.log(`Successfully loaded user ${userId}:`, user.name);
|
|
348
|
-
});
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
### Success with Request Parameters
|
|
352
|
-
|
|
353
|
-
```typescript
|
|
354
|
-
requestor.onSuccessRequest((userId) => {
|
|
355
|
-
console.log(`Successfully processed user ${userId}`);
|
|
356
|
-
});
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
### Success with Full Context
|
|
360
|
-
|
|
361
|
-
```typescript
|
|
362
|
-
requestor.onSuccessWithRequest(({ body, requestParams }) => {
|
|
363
|
-
const [userId] = requestParams;
|
|
364
|
-
console.log(`User ${userId}:`, body.name);
|
|
365
|
-
});
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
### Success or Error Handler
|
|
369
|
-
|
|
370
|
-
Execute callback on completion regardless of outcome.
|
|
371
|
-
|
|
372
|
-
```typescript
|
|
373
|
-
requestor.onSuccessOrError(() => {
|
|
374
|
-
console.log('Request completed');
|
|
375
|
-
this.hideLoadingSpinner();
|
|
376
|
-
});
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
### Default Success Handler
|
|
380
|
-
|
|
381
|
-
```typescript
|
|
382
|
-
requestor.useDefaultSuccessHandler();
|
|
383
|
-
// Logs 'Success' by default, or uses configured handler
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
**Note:** See [RequestStateStoreConfig Documentation](./REQUEST-STATE-STORE-CONFIG.md) for complete details on configuring global success handlers.
|
|
387
|
-
|
|
388
|
-
## Advanced Patterns
|
|
389
|
-
|
|
390
|
-
### Chaining Handlers
|
|
391
|
-
|
|
392
|
-
```typescript
|
|
393
|
-
const requestor = createRequestor(
|
|
394
|
-
(userId: number) => this.http.get<User>(`/api/users/${userId}`)
|
|
395
|
-
)
|
|
396
|
-
.onSuccess((user) => {
|
|
397
|
-
this.userCache.set(user.id, user);
|
|
398
|
-
})
|
|
399
|
-
.onError((error) => {
|
|
400
|
-
this.logger.error('Failed to load user', error);
|
|
401
|
-
})
|
|
402
|
-
.onSuccessOrError(() => {
|
|
403
|
-
this.loadingService.hide();
|
|
404
|
-
});
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
### Resetting State
|
|
408
|
-
|
|
409
|
-
```typescript
|
|
410
|
-
requestor.reset(); // Resets to notStarted state
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
### Manual Cleanup
|
|
414
|
-
|
|
415
|
-
```typescript
|
|
416
|
-
requestor.destroy(); // Manually trigger cleanup
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
### Projection/Transformation
|
|
420
|
-
|
|
421
|
-
Transform the response before it's stored in state.
|
|
422
|
-
|
|
423
|
-
```typescript
|
|
424
|
-
const requestor = createRequestor(
|
|
425
|
-
(id: number) => this.http.get<UserDTO>(`/api/users/${id}`),
|
|
426
|
-
(dto: UserDTO) => ({
|
|
427
|
-
id: dto.user_id,
|
|
428
|
-
name: `${dto.first_name} ${dto.last_name}`,
|
|
429
|
-
email: dto.email_address
|
|
430
|
-
} as User)
|
|
431
|
-
);
|
|
432
|
-
|
|
433
|
-
// The state will contain the transformed User, not UserDTO
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
### Cancellation Token
|
|
437
|
-
|
|
438
|
-
```typescript
|
|
439
|
-
const requestor = createRequestor(
|
|
440
|
-
(id: number | CancellationToken) => {
|
|
441
|
-
if (id instanceof CancellationToken) {
|
|
442
|
-
return of(null); // Handle cancellation
|
|
443
|
-
}
|
|
444
|
-
return this.http.get(`/api/users/${id}`);
|
|
445
|
-
},
|
|
446
|
-
{ strategy: RequestStrategy.cancelPrevious }
|
|
447
|
-
);
|
|
448
|
-
|
|
449
|
-
requestor.request(new CancellationToken()); // Explicit cancellation
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
## Request State Types
|
|
453
|
-
|
|
454
|
-
### `RequestStatus` Enum
|
|
455
|
-
|
|
456
|
-
```typescript
|
|
457
|
-
enum RequestStatus {
|
|
458
|
-
notStarted, // Initial state
|
|
459
|
-
inProgress, // Request is in flight
|
|
460
|
-
success, // Request completed successfully
|
|
461
|
-
fail, // Request failed
|
|
462
|
-
cancelled // Request was cancelled
|
|
463
|
-
}
|
|
464
|
-
```
|
|
465
|
-
|
|
466
|
-
### State Type Definitions
|
|
467
|
-
|
|
468
|
-
```typescript
|
|
469
|
-
type RequestStateNotStarted = { status: RequestStatus.notStarted }
|
|
470
|
-
type RequestStateInProgress = { status: RequestStatus.inProgress }
|
|
471
|
-
type RequestStateSuccess<T> = { status: RequestStatus.success; body: T }
|
|
472
|
-
type RequestStateError = { status: RequestStatus.fail; error: any }
|
|
473
|
-
type RequestStateCancelled = { status: RequestStatus.cancelled }
|
|
474
|
-
|
|
475
|
-
type RequestState<T> =
|
|
476
|
-
| RequestStateNotStarted
|
|
477
|
-
| RequestStateInProgress
|
|
478
|
-
| RequestStateSuccess<T>
|
|
479
|
-
| RequestStateError
|
|
480
|
-
| RequestStateCancelled
|
|
481
|
-
```
|
|
482
|
-
|
|
483
|
-
## Common Patterns
|
|
484
|
-
|
|
485
|
-
### Loading Pattern
|
|
486
|
-
|
|
487
|
-
```typescript
|
|
488
|
-
@Component({
|
|
489
|
-
template: `
|
|
490
|
-
@if (users.$isInProgress()) {
|
|
491
|
-
<mat-spinner />
|
|
492
|
-
} @else if (users.$isSuccess()) {
|
|
493
|
-
<user-list [users]="users.$selectResponse()!" />
|
|
494
|
-
} @else if (users.$isError()) {
|
|
495
|
-
<error-message [error]="users.$selectError()!" />
|
|
496
|
-
}
|
|
497
|
-
`
|
|
498
|
-
})
|
|
499
|
-
export class UserListComponent {
|
|
500
|
-
private http = inject(HttpClient);
|
|
501
|
-
|
|
502
|
-
users = createRequestor(
|
|
503
|
-
() => this.http.get<User[]>('/api/users'),
|
|
504
|
-
{ autoRequest: true }
|
|
505
|
-
);
|
|
506
|
-
}
|
|
507
|
-
```
|
|
508
|
-
|
|
509
|
-
### Master-Detail Pattern
|
|
510
|
-
|
|
511
|
-
```typescript
|
|
512
|
-
export class UserDetailComponent {
|
|
513
|
-
private http = inject(HttpClient);
|
|
514
|
-
private route = inject(ActivatedRoute);
|
|
515
|
-
|
|
516
|
-
userId = toSignal(this.route.params.pipe(map(p => +p['id'])));
|
|
517
|
-
userIdArray = computed(() => [this.userId()]);
|
|
518
|
-
|
|
519
|
-
user = createRequestor(
|
|
520
|
-
(id: number) => this.http.get<User>(`/api/users/${id}`)
|
|
521
|
-
).requestWith(this.userIdArray);
|
|
522
|
-
}
|
|
523
|
-
```
|
|
524
|
-
|
|
525
|
-
### Search Pattern
|
|
526
|
-
|
|
527
|
-
```typescript
|
|
528
|
-
export class SearchComponent {
|
|
529
|
-
searchTerm = signal('');
|
|
530
|
-
|
|
531
|
-
searchResults = createRequestor(
|
|
532
|
-
(term: string) => this.http.get<SearchResult[]>(`/api/search?q=${term}`),
|
|
533
|
-
{ strategy: RequestStrategy.cancelPrevious }
|
|
534
|
-
).requestWith(
|
|
535
|
-
toObservable(this.searchTerm).pipe(
|
|
536
|
-
debounceTime(300),
|
|
537
|
-
map(term => [term])
|
|
538
|
-
)
|
|
539
|
-
);
|
|
540
|
-
}
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
### Form Submission Pattern
|
|
544
|
-
|
|
545
|
-
```typescript
|
|
546
|
-
export class UserFormComponent {
|
|
547
|
-
saveUser = createRequestor(
|
|
548
|
-
(user: User) => this.http.post<User>('/api/users', user),
|
|
549
|
-
{ strategy: RequestStrategy.singleUse }
|
|
550
|
-
)
|
|
551
|
-
.onSuccess((savedUser) => {
|
|
552
|
-
this.router.navigate(['/users', savedUser.id]);
|
|
553
|
-
})
|
|
554
|
-
.onError((error) => {
|
|
555
|
-
this.showErrorMessage(error.message);
|
|
556
|
-
});
|
|
557
|
-
|
|
558
|
-
onSubmit(user: User) {
|
|
559
|
-
this.saveUser.request(user);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
```
|
|
563
|
-
|
|
564
|
-
## Migration from Observable Patterns
|
|
565
|
-
|
|
566
|
-
### Before (Traditional Observable)
|
|
567
|
-
|
|
568
|
-
```typescript
|
|
569
|
-
export class UserService {
|
|
570
|
-
private loading$ = new BehaviorSubject<boolean>(false);
|
|
571
|
-
private error$ = new BehaviorSubject<HttpErrorResponse | null>(null);
|
|
572
|
-
private user$ = new BehaviorSubject<User | null>(null);
|
|
573
|
-
|
|
574
|
-
getUser(id: number) {
|
|
575
|
-
this.loading$.next(true);
|
|
576
|
-
this.error$.next(null);
|
|
577
|
-
|
|
578
|
-
this.http.get<User>(`/api/users/${id}`).subscribe({
|
|
579
|
-
next: (user) => {
|
|
580
|
-
this.user$.next(user);
|
|
581
|
-
this.loading$.next(false);
|
|
582
|
-
},
|
|
583
|
-
error: (error) => {
|
|
584
|
-
this.error$.next(error);
|
|
585
|
-
this.loading$.next(false);
|
|
586
|
-
}
|
|
587
|
-
});
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
```
|
|
591
|
-
|
|
592
|
-
### After (With RequestStateStore)
|
|
593
|
-
|
|
594
|
-
```typescript
|
|
595
|
-
export class UserService {
|
|
596
|
-
private http = inject(HttpClient);
|
|
597
|
-
|
|
598
|
-
userRequestor = createRequestor(
|
|
599
|
-
(id: number) => this.http.get<User>(`/api/users/${id}`)
|
|
600
|
-
);
|
|
601
|
-
|
|
602
|
-
// Access via signals
|
|
603
|
-
isLoading = this.userRequestor.$isInProgress;
|
|
604
|
-
error = this.userRequestor.$selectError;
|
|
605
|
-
user = this.userRequestor.$selectResponse;
|
|
606
|
-
|
|
607
|
-
getUser(id: number) {
|
|
608
|
-
this.userRequestor.request(id);
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
```
|
|
612
|
-
|
|
613
|
-
## See Also
|
|
614
|
-
|
|
615
|
-
- [createRequestor Function](./CREATE-REQUESTOR.md)
|
|
616
|
-
- [RequestStateStoreConfig](./REQUEST-STATE-STORE-CONFIG.md)
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { RequestState, RequestStateError, RequestStateInProgress, RequestStateNotStarted, RequestStateSuccess, RequestStatus } from "./types";
|
|
2
|
-
|
|
3
|
-
export function isErrorState<T>(state: RequestState<T>): state is RequestStateError {
|
|
4
|
-
return state.status === RequestStatus.fail;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function isSuccessState<T>(state: RequestState<T>): state is RequestStateSuccess<T> {
|
|
8
|
-
return state.status === RequestStatus.success;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function isSuccessOrErrorState<T>(state: RequestState<T>): state is (RequestStateSuccess<T> | RequestStateError) {
|
|
12
|
-
return state.status === RequestStatus.success || state.status === RequestStatus.fail;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function createSuccess<T>(body: T): RequestStateSuccess<T> {
|
|
16
|
-
return { status: RequestStatus.success, body };
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function createFailure(error: any): RequestStateError {
|
|
20
|
-
return { status: RequestStatus.fail, error };
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export const notStarted: RequestStateNotStarted = { status: RequestStatus.notStarted };
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
export const inProgress: RequestStateInProgress = { status: RequestStatus.inProgress };
|
|
27
|
-
|
|
28
|
-
export function statusIsSuccessOrInProgress( status: RequestStatus) {
|
|
29
|
-
return [RequestStatus.success, RequestStatus.inProgress].includes(status);
|
|
30
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { NgModule } from '@angular/core';
|
|
2
|
-
import { HttpSuccessStateDirective } from './directives/http-success-state-directive';
|
|
3
|
-
import { HttpRequestStateDirective } from './directives/request-state-directive';
|
|
4
|
-
import { HttpErrorStateDirective } from './directives/http-error-state-directive';
|
|
5
|
-
import { HttpInProgressStateDirective } from './directives/http-inProgress-state-directive';
|
|
6
|
-
import { HttpNotStartedStateDirective } from './directives/http-notStarted-state-directive';
|
|
7
|
-
|
|
8
|
-
@NgModule({
|
|
9
|
-
imports: [
|
|
10
|
-
HttpSuccessStateDirective,
|
|
11
|
-
HttpRequestStateDirective,
|
|
12
|
-
HttpErrorStateDirective,
|
|
13
|
-
HttpInProgressStateDirective,
|
|
14
|
-
HttpNotStartedStateDirective,
|
|
15
|
-
],
|
|
16
|
-
exports: [
|
|
17
|
-
HttpSuccessStateDirective,
|
|
18
|
-
HttpRequestStateDirective,
|
|
19
|
-
HttpErrorStateDirective,
|
|
20
|
-
HttpInProgressStateDirective,
|
|
21
|
-
HttpNotStartedStateDirective,
|
|
22
|
-
]
|
|
23
|
-
}) export class HttpRequestModule { }
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { RequestStatus } from "../types";
|
|
2
|
-
|
|
3
|
-
export interface HttpRequestStateViewContext<T> {
|
|
4
|
-
$implicit?: HttpRequestStateAny<T>;
|
|
5
|
-
state?: HttpRequestStateAny<T>;
|
|
6
|
-
status: {
|
|
7
|
-
inProgress: boolean;
|
|
8
|
-
notStarted: boolean;
|
|
9
|
-
success: boolean;
|
|
10
|
-
error: boolean;
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export type HttpRequestStateAny<T> = {
|
|
15
|
-
status: RequestStatus;
|
|
16
|
-
body?: T;
|
|
17
|
-
error?: any;
|
|
18
|
-
}
|