@blueprint-ts/core 2.0.0 → 4.0.0-beta.1

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.
Files changed (208) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +25 -1
  3. package/docs/.vitepress/config.ts +80 -23
  4. package/docs/index.md +6 -63
  5. package/docs/{services/laravel → laravel}/pagination.md +19 -6
  6. package/docs/{services/laravel → laravel}/requests.md +2 -2
  7. package/docs/services/pagination/index.md +46 -0
  8. package/docs/services/pagination/infinite-scroller.md +19 -0
  9. package/docs/services/pagination/page-aware.md +46 -0
  10. package/docs/services/pagination/state-pagination.md +77 -0
  11. package/docs/services/pagination/updating-rows.md +36 -0
  12. package/docs/services/persistence/index.md +46 -0
  13. package/docs/services/requests/abort-requests.md +25 -0
  14. package/docs/services/requests/bulk-requests.md +70 -0
  15. package/docs/services/requests/drivers.md +50 -0
  16. package/docs/services/requests/error-handling.md +137 -0
  17. package/docs/services/requests/events.md +31 -0
  18. package/docs/services/requests/getting-started.md +201 -0
  19. package/docs/services/requests/headers.md +40 -0
  20. package/docs/services/requests/loading.md +63 -0
  21. package/docs/services/requests/request-bodies.md +59 -0
  22. package/docs/services/requests/responses.md +34 -0
  23. package/docs/services/support/deferred-promise.md +63 -0
  24. package/docs/services/support/helpers.md +77 -0
  25. package/docs/services/support/index.md +6 -0
  26. package/docs/upgrading/v1-to-v2.md +64 -0
  27. package/docs/upgrading/v2-to-v3.md +52 -0
  28. package/docs/upgrading/v3-to-v4.md +171 -0
  29. package/docs/upgrading.md +0 -0
  30. package/docs/vue/composables/use-confirm-dialog.md +96 -0
  31. package/docs/vue/composables/use-global-checkbox.md +73 -0
  32. package/docs/vue/composables/use-is-empty.md +26 -0
  33. package/docs/vue/composables/use-is-open-from-var.md +32 -0
  34. package/docs/vue/composables/use-is-open.md +28 -0
  35. package/docs/vue/composables/use-model-wrapper.md +29 -0
  36. package/docs/vue/composables/use-on-open.md +26 -0
  37. package/docs/vue/forms/arrays.md +45 -0
  38. package/docs/vue/forms/errors.md +52 -0
  39. package/docs/vue/forms/index.md +99 -0
  40. package/docs/vue/forms/payloads.md +99 -0
  41. package/docs/vue/forms/persistence.md +19 -0
  42. package/docs/vue/forms/state-and-properties.md +26 -0
  43. package/docs/vue/forms/utilities.md +27 -0
  44. package/docs/vue/forms/validation.md +189 -0
  45. package/docs/vue/requests/loading.md +51 -0
  46. package/docs/vue/{requests → router}/route-resource-binding.md +33 -27
  47. package/docs/vue/state.md +27 -11
  48. package/package.json +9 -10
  49. package/release-tool.json +22 -3
  50. package/src/{service/bulkRequests → bulkRequests}/BulkRequestSender.ts +29 -17
  51. package/src/{service/bulkRequests → bulkRequests}/BulkRequestWrapper.ts +5 -5
  52. package/src/laravel/pagination/dataDrivers/RequestDriver.ts +30 -0
  53. package/src/laravel/pagination/index.ts +6 -0
  54. package/src/{service/pagination → pagination}/BasePaginator.ts +35 -0
  55. package/src/{service/pagination → pagination}/InfiniteScroller.ts +1 -0
  56. package/src/{service/pagination → pagination}/PageAwarePaginator.ts +19 -21
  57. package/src/{service/pagination → pagination}/StatePaginator.ts +2 -8
  58. package/src/{service/pagination → pagination}/index.ts +1 -1
  59. package/src/{service/requests → requests}/BaseRequest.ts +2 -2
  60. package/src/requests/ErrorHandler.ts +144 -0
  61. package/src/requests/RequestErrorRouter.ts +89 -0
  62. package/src/requests/bodies/FormDataBody.ts +81 -0
  63. package/src/requests/exceptions/BadGatewayException.ts +3 -0
  64. package/src/requests/exceptions/BadRequestException.ts +3 -0
  65. package/src/requests/exceptions/ConflictException.ts +3 -0
  66. package/src/requests/exceptions/ForbiddenException.ts +3 -0
  67. package/src/requests/exceptions/GatewayTimeoutException.ts +3 -0
  68. package/src/requests/exceptions/GoneException.ts +3 -0
  69. package/src/requests/exceptions/InvalidJsonException.ts +15 -0
  70. package/src/requests/exceptions/LockedException.ts +3 -0
  71. package/src/requests/exceptions/MethodNotAllowedException.ts +3 -0
  72. package/src/requests/exceptions/NotImplementedException.ts +3 -0
  73. package/src/requests/exceptions/PayloadTooLargeException.ts +3 -0
  74. package/src/requests/exceptions/PreconditionFailedException.ts +3 -0
  75. package/src/requests/exceptions/RequestTimeoutException.ts +3 -0
  76. package/src/requests/exceptions/ServiceUnavailableException.ts +3 -0
  77. package/src/requests/exceptions/TooManyRequestsException.ts +3 -0
  78. package/src/requests/exceptions/UnsupportedMediaTypeException.ts +3 -0
  79. package/src/requests/exceptions/index.ts +51 -0
  80. package/src/requests/factories/FormDataFactory.ts +14 -0
  81. package/src/{service/requests → requests}/index.ts +2 -2
  82. package/src/{service/support → support}/DeferredPromise.ts +1 -1
  83. package/src/support/index.ts +4 -0
  84. package/src/vue/composables/useConfirmDialog.ts +5 -1
  85. package/src/vue/composables/useModelWrapper.ts +3 -0
  86. package/src/vue/forms/BaseForm.ts +509 -405
  87. package/src/vue/forms/PropertyAwareArray.ts +3 -4
  88. package/src/vue/forms/index.ts +4 -4
  89. package/src/vue/forms/validation/index.ts +5 -2
  90. package/src/vue/forms/validation/rules/ConfirmedRule.ts +3 -3
  91. package/src/vue/forms/validation/rules/EmailRule.ts +23 -0
  92. package/src/vue/forms/validation/rules/JsonRule.ts +28 -0
  93. package/src/vue/forms/validation/types/BidirectionalRule.ts +2 -2
  94. package/src/vue/forms/validation/types/ValidationRules.ts +15 -0
  95. package/src/vue/index.ts +3 -3
  96. package/src/vue/requests/factories/VueRequestLoaderFactory.ts +3 -2
  97. package/src/vue/requests/loaders/VueRequestBatchLoader.ts +6 -1
  98. package/src/vue/requests/loaders/VueRequestLoader.ts +1 -1
  99. package/src/vue/router/routeResourceBinding/types.ts +3 -3
  100. package/src/vue/state/State.ts +38 -50
  101. package/tests/service/helpers/mergeDeep.test.ts +1 -1
  102. package/tests/service/laravel/pagination/dataDrivers/RequestDriver.test.ts +3 -3
  103. package/tests/service/laravel/requests/JsonBaseRequest.test.ts +4 -4
  104. package/tests/service/laravel/requests/PaginationJsonBaseRequest.test.ts +3 -3
  105. package/tests/service/laravel/requests/responses/JsonResponse.test.ts +2 -2
  106. package/tests/service/laravel/requests/responses/PaginationResponse.test.ts +2 -2
  107. package/tests/service/pagination/dtos/PaginationDataDto.test.ts +1 -1
  108. package/tests/service/pagination/factories/VuePaginationDriverFactory.test.ts +2 -2
  109. package/tests/service/pagination/frontendDrivers/VuePaginationDriver.test.ts +1 -1
  110. package/tests/service/requests/ErrorHandler.test.ts +61 -58
  111. package/tests/service/requests/FormDataBody.test.ts +63 -0
  112. package/tests/vue/forms/BaseForm.behavior.test.ts +98 -0
  113. package/tests/vue/forms/BaseForm.transformers.test.ts +109 -0
  114. package/docs/.vitepress/theme/Layout.vue +0 -14
  115. package/docs/.vitepress/theme/components/VersionSelector.vue +0 -64
  116. package/docs/.vitepress/theme/index.js +0 -13
  117. package/docs/services/requests/index.md +0 -74
  118. package/docs/vue/forms.md +0 -326
  119. package/examples/files/7z2404-x64.exe +0 -0
  120. package/examples/index.html +0 -14
  121. package/examples/js/app.js +0 -8
  122. package/examples/js/router.js +0 -22
  123. package/examples/js/view/App.vue +0 -49
  124. package/examples/js/view/layout/DemoPage.vue +0 -28
  125. package/examples/js/view/pagination/Pagination.vue +0 -28
  126. package/examples/js/view/pagination/components/errorPagination/ErrorPagination.vue +0 -71
  127. package/examples/js/view/pagination/components/errorPagination/GetProductsRequest.ts +0 -54
  128. package/examples/js/view/pagination/components/infiniteScrolling/GetProductsRequest.ts +0 -50
  129. package/examples/js/view/pagination/components/infiniteScrolling/InfiniteScrolling.vue +0 -57
  130. package/examples/js/view/pagination/components/tablePagination/GetProductsRequest.ts +0 -50
  131. package/examples/js/view/pagination/components/tablePagination/TablePagination.vue +0 -63
  132. package/examples/js/view/requests/Requests.vue +0 -34
  133. package/examples/js/view/requests/components/abortableRequest/AbortableRequest.vue +0 -36
  134. package/examples/js/view/requests/components/abortableRequest/GetProductsRequest.ts +0 -25
  135. package/examples/js/view/requests/components/fileDownloadRequest/DownloadFileRequest.ts +0 -15
  136. package/examples/js/view/requests/components/fileDownloadRequest/FileDownloadRequest.vue +0 -44
  137. package/examples/js/view/requests/components/getRequestWithDynamicParams/GetProductsRequest.ts +0 -34
  138. package/examples/js/view/requests/components/getRequestWithDynamicParams/GetRequestWithDynamicParams.vue +0 -59
  139. package/examples/js/view/requests/components/serverErrorRequest/ServerErrorRequest.ts +0 -21
  140. package/examples/js/view/requests/components/serverErrorRequest/ServerErrorRequest.vue +0 -53
  141. package/src/service/laravel/pagination/contracts/PaginationParamsContract.ts +0 -4
  142. package/src/service/laravel/pagination/dataDrivers/RequestDriver.ts +0 -32
  143. package/src/service/laravel/pagination/index.ts +0 -7
  144. package/src/service/requests/ErrorHandler.ts +0 -64
  145. package/src/service/requests/bodies/FormDataBody.ts +0 -41
  146. package/src/service/requests/exceptions/index.ts +0 -19
  147. package/src/service/requests/factories/FormDataFactory.ts +0 -9
  148. package/src/service/support/index.ts +0 -3
  149. /package/src/{service/bulkRequests → bulkRequests}/BulkRequestEvent.enum.ts +0 -0
  150. /package/src/{service/bulkRequests → bulkRequests}/index.ts +0 -0
  151. /package/src/{service/laravel → laravel}/pagination/contracts/PaginationResponseBodyContract.ts +0 -0
  152. /package/src/{service/laravel → laravel}/requests/JsonBaseRequest.ts +0 -0
  153. /package/src/{service/laravel → laravel}/requests/PaginationJsonBaseRequest.ts +0 -0
  154. /package/src/{service/laravel → laravel}/requests/index.ts +0 -0
  155. /package/src/{service/laravel → laravel}/requests/responses/JsonResponse.ts +0 -0
  156. /package/src/{service/laravel → laravel}/requests/responses/PaginationResponse.ts +0 -0
  157. /package/src/{service/pagination → pagination}/Paginator.ts +0 -0
  158. /package/src/{service/pagination → pagination}/contracts/BaseViewDriverContract.ts +0 -0
  159. /package/src/{service/pagination → pagination}/contracts/BaseViewDriverFactoryContract.ts +0 -0
  160. /package/src/{service/pagination → pagination}/contracts/PaginateableRequestContract.ts +0 -0
  161. /package/src/{service/pagination → pagination}/contracts/PaginationDataDriverContract.ts +0 -0
  162. /package/src/{service/pagination → pagination}/contracts/PaginationResponseContract.ts +0 -0
  163. /package/src/{service/pagination → pagination}/contracts/PaginatorLoadDataOptions.ts +0 -0
  164. /package/src/{service/pagination → pagination}/contracts/StatePaginationDataDriverContract.ts +0 -0
  165. /package/src/{service/pagination → pagination}/contracts/ViewDriverContract.ts +0 -0
  166. /package/src/{service/pagination → pagination}/contracts/ViewDriverFactoryContract.ts +0 -0
  167. /package/src/{service/pagination → pagination}/dataDrivers/ArrayDriver.ts +0 -0
  168. /package/src/{service/pagination → pagination}/dtos/PaginationDataDto.ts +0 -0
  169. /package/src/{service/pagination → pagination}/dtos/StatePaginationDataDto.ts +0 -0
  170. /package/src/{service/pagination → pagination}/factories/VueBaseViewDriverFactory.ts +0 -0
  171. /package/src/{service/pagination → pagination}/factories/VuePaginationDriverFactory.ts +0 -0
  172. /package/src/{service/pagination → pagination}/frontendDrivers/VueBaseViewDriver.ts +0 -0
  173. /package/src/{service/pagination → pagination}/frontendDrivers/VuePaginationDriver.ts +0 -0
  174. /package/src/{service/persistenceDrivers → persistenceDrivers}/LocalStorageDriver.ts +0 -0
  175. /package/src/{service/persistenceDrivers → persistenceDrivers}/NonPersistentDriver.ts +0 -0
  176. /package/src/{service/persistenceDrivers → persistenceDrivers}/SessionStorageDriver.ts +0 -0
  177. /package/src/{service/persistenceDrivers → persistenceDrivers}/index.ts +0 -0
  178. /package/src/{service/persistenceDrivers → persistenceDrivers}/types/PersistenceDriver.ts +0 -0
  179. /package/src/{service/requests → requests}/RequestEvents.enum.ts +0 -0
  180. /package/src/{service/requests → requests}/RequestMethod.enum.ts +0 -0
  181. /package/src/{service/requests → requests}/bodies/JsonBody.ts +0 -0
  182. /package/src/{service/requests → requests}/contracts/AbortableRequestContract.ts +0 -0
  183. /package/src/{service/requests → requests}/contracts/BaseRequestContract.ts +0 -0
  184. /package/src/{service/requests → requests}/contracts/BodyContract.ts +0 -0
  185. /package/src/{service/requests → requests}/contracts/BodyFactoryContract.ts +0 -0
  186. /package/src/{service/requests → requests}/contracts/DriverConfigContract.ts +0 -0
  187. /package/src/{service/requests → requests}/contracts/HeadersContract.ts +0 -0
  188. /package/src/{service/requests → requests}/contracts/RequestDriverContract.ts +0 -0
  189. /package/src/{service/requests → requests}/contracts/RequestLoaderContract.ts +0 -0
  190. /package/src/{service/requests → requests}/contracts/RequestLoaderFactoryContract.ts +0 -0
  191. /package/src/{service/requests → requests}/contracts/ResponseContract.ts +0 -0
  192. /package/src/{service/requests → requests}/drivers/contracts/ResponseHandlerContract.ts +0 -0
  193. /package/src/{service/requests → requests}/drivers/fetch/FetchDriver.ts +0 -0
  194. /package/src/{service/requests → requests}/drivers/fetch/FetchResponse.ts +0 -0
  195. /package/src/{service/requests → requests}/exceptions/NoResponseReceivedException.ts +0 -0
  196. /package/src/{service/requests → requests}/exceptions/NotFoundException.ts +0 -0
  197. /package/src/{service/requests → requests}/exceptions/PageExpiredException.ts +0 -0
  198. /package/src/{service/requests → requests}/exceptions/ResponseBodyException.ts +0 -0
  199. /package/src/{service/requests → requests}/exceptions/ResponseException.ts +0 -0
  200. /package/src/{service/requests → requests}/exceptions/ServerErrorException.ts +0 -0
  201. /package/src/{service/requests → requests}/exceptions/UnauthorizedException.ts +0 -0
  202. /package/src/{service/requests → requests}/exceptions/ValidationException.ts +0 -0
  203. /package/src/{service/requests → requests}/factories/JsonBodyFactory.ts +0 -0
  204. /package/src/{service/requests → requests}/responses/BaseResponse.ts +0 -0
  205. /package/src/{service/requests → requests}/responses/BlobResponse.ts +0 -0
  206. /package/src/{service/requests → requests}/responses/JsonResponse.ts +0 -0
  207. /package/src/{service/requests → requests}/responses/PlainTextResponse.ts +0 -0
  208. /package/src/{helpers.ts → support/helpers.ts} +0 -0
package/docs/vue/forms.md DELETED
@@ -1,326 +0,0 @@
1
- # BaseForm Documentation
2
-
3
- ## Overview
4
-
5
- `BaseForm` is a powerful and flexible TypeScript class for handling form state, validation, and submission in Vue
6
- applications. It provides a comprehensive solution for managing form data with features like:
7
-
8
- - Type-safe form state management
9
- - Dirty state tracking for individual fields
10
- - Error handling and field validation
11
- - Form persistence between page reloads
12
- - Support for complex nested objects and arrays
13
- - Automatic transformation of form values to API payloads
14
-
15
- ## Key Features
16
-
17
- ### 1. Type-Safe Form Management
18
-
19
- The `BaseForm` is a generic class that takes two type parameters:
20
-
21
- - `RequestBody`: The shape of the data that will be sent to the server
22
- - `FormBody`: The shape of the form's internal state, which can differ from the request payload
23
-
24
- ````typescript
25
- class MyForm extends BaseForm<MyRequestPayload, MyFormState> {
26
- // ...
27
- }
28
- ````
29
-
30
- ### 2. Form State Persistence
31
-
32
- Forms can automatically save their state to browser storage (session, local, etc.), allowing users to navigate away and
33
- return without losing their input.
34
-
35
- ````typescript
36
- protected override getPersistenceDriver(): PersistenceDriver
37
- {
38
- return new SessionStorageDriver() // Or LocalStorageDriver, etc.
39
- }
40
- ````
41
-
42
- ### 3. Transformations and Getters
43
-
44
- Transform form values before they are sent to the server using getter methods:
45
-
46
- ````typescript
47
- protected getStartedAt(): string {
48
- return DateTime.fromFormat(`${this.state.start_date} ${this.state.start_time}`, 'dd.MM.yyyy HH:mm').toISO()
49
- }
50
- ````
51
-
52
- ### 4. Error Handling and Validation
53
-
54
- Map server-side validation errors to specific form fields, with support for nested fields:
55
-
56
- ````typescript
57
- protected override errorMap: { [serverKey: string]: string | string[] } = {
58
- started_at: ['start_date', 'start_time'],
59
- ended_at: ['end_date', 'end_time']
60
- }
61
- ````
62
-
63
- ### 5. Array Management
64
-
65
- Special support for arrays with the class `PropertyAwareArray`, enabling reactive updates to array items:
66
-
67
- ````typescript
68
- public addPosition(): void {
69
- this.addToArrayProperty('positions', {
70
- index: this.properties.positions.length + 1,
71
- gross_amount: null,
72
- vat_rate: VatRateEnum.VAT_RATE_19,
73
- booking_account_category_id: null
74
- })
75
- }
76
- ````
77
-
78
- ## Core Concepts
79
-
80
- ### State and Dirty Tracking
81
-
82
- `BaseForm` tracks the original state and current state of each form field, automatically computing "dirty" status for
83
- fields that have been changed.
84
-
85
- ````typescript
86
- // Check if any field in the form has been modified
87
- form.isDirty()
88
- ````
89
-
90
- ### The Properties Object
91
-
92
- The `properties` getter provides access to each form field with its model, errors, and dirty status:
93
-
94
- ````html
95
-
96
- <template>
97
- <input v-model="form.properties.email.model.value" />
98
- <div v-if="form.properties.email.dirty">This field has been changed</div>
99
- <div v-if="form.properties.email.errors.length">{{ form.properties.email.errors[0] }}</div>
100
- </template>
101
- ````
102
-
103
- ### Form Submission
104
-
105
- Build a payload for API submission with:
106
-
107
- ````typescript
108
- const payload = form.buildPayload()
109
- ````
110
-
111
- ## How to Use
112
-
113
- ### 1. Create a Form Class
114
-
115
- ````typescript
116
- import { BaseForm, type PersistenceDriver, SessionStorageDriver } from '@hank-it/ui/vue/forms'
117
-
118
- interface MyFormState {
119
- name: string
120
- email: string
121
- }
122
-
123
- interface MyRequestPayload {
124
- name: string
125
- email: string
126
- timestamp: string // Added field not in the form
127
- }
128
-
129
- class MyForm extends BaseForm<MyRequestPayload, MyFormState> {
130
- // Fields to add to the final payload that aren't in the form state
131
- protected override append: string[] = ['timestamp']
132
-
133
- // Fields to exclude from the final payload
134
- protected override ignore: string[] = []
135
-
136
- // Map server error keys to form field names
137
- protected override errorMap: { [serverKey: string]: string | string[] } = {}
138
-
139
- public constructor() {
140
- super({
141
- name: '',
142
- email: ''
143
- }, { persist: true, persistSuffix: 'optional-suffix' })
144
- }
145
-
146
- // Use session storage for persistence
147
- protected override getPersistenceDriver(): PersistenceDriver {
148
- return new SessionStorageDriver()
149
- }
150
-
151
- // Generate a timestamp for the request
152
- protected getTimestamp(): string {
153
- return new Date().toISOString()
154
- }
155
- }
156
- ````
157
-
158
- ### 2. Use in Components
159
-
160
- ````vue
161
- <template>
162
- <form @submit.prevent="submitForm">
163
- <div>
164
- <label>Name</label>
165
- <input v-model="form.properties.name.model.value" />
166
- <div v-if="form.properties.name.errors.length" class="error">
167
- {{ form.properties.name.errors[0] }}
168
- </div>
169
- </div>
170
-
171
- <div>
172
- <label>Email</label>
173
- <input v-model="form.properties.email.model.value" />
174
- <div v-if="form.properties.email.errors.length" class="error">
175
- {{ form.properties.email.errors[0] }}
176
- </div>
177
- </div>
178
-
179
- <button type="submit" :disabled="!form.isDirty()">Submit</button>
180
- <button type="button" @click="form.reset()">Reset</button>
181
- </form>
182
- </template>
183
-
184
- <script setup>
185
- import { MyForm } from './MyForm'
186
-
187
- const form = new MyForm({
188
- name: '',
189
- email: ''
190
- })
191
-
192
- async function submitForm() {
193
- try {
194
- const payload = form.buildPayload()
195
- await api.submitForm(payload)
196
- // Success handling
197
- } catch (error) {
198
- if (error.response?.data?.errors) {
199
- form.fillErrors(error.response.data.errors)
200
- }
201
- }
202
- }
203
- </script>
204
- ````
205
-
206
- ## Working with Arrays
207
- The `PropertyAwareArray` class enables special handling for array items. Each value of objects in the PropertyAwareArray will receive a v-model, errors, etc.:
208
-
209
- ````typescript
210
- import { BaseForm, PropertyAwareArray } from '@hank-it/ui/vue/forms'
211
-
212
- export interface FormWithPositions {
213
- // ...other fields
214
- positions: PositionItem[]
215
- }
216
-
217
- export class MyComplexForm extends BaseForm<RequestType, FormWithPositions> {
218
- constructor() {
219
- super({
220
- // ...other defaults
221
- positions: new PropertyAwareArray([
222
- { id: 1, value: '' }
223
- ])
224
- })
225
- }
226
-
227
- // Add a new position to the array
228
- public addPosition(): void {
229
- this.addToArrayProperty('positions', {
230
- id: this.properties.positions.length + 1,
231
- value: ''
232
- })
233
- }
234
-
235
- // Remove a position by id
236
- public removePosition(id: number): void {
237
- this.state.positions = new PropertyAwareArray(
238
- this.state.positions.filter(position => position.id !== id)
239
- )
240
- this.resetPositionIds()
241
- }
242
-
243
- // Reset the sequential IDs after removing items
244
- protected resetPositionIds(): void {
245
- let count = 1
246
- this.state.positions.forEach(position => {
247
- position.id = count
248
- count++
249
- })
250
- }
251
- }
252
-
253
- const form = new MyComplexForm()
254
- const id = form.properties.positions[0].id.model.value
255
- ````
256
-
257
- ## Advanced Features
258
- ### 1. Form Reset
259
- Revert all changes to the original state:
260
-
261
- ````typescript
262
- form.reset()
263
- ````
264
-
265
- ### 2. Error Handling
266
- Fill form with validation errors from a server response:
267
-
268
- ````typescript
269
- try {
270
- await submitForm(form.buildPayload())
271
- } catch (error) {
272
- form.fillErrors(error.response.data.errors)
273
- }
274
- ````
275
-
276
- The `fileErrors` method currently only supports the Laravel style dot notation errors.
277
-
278
- ### 3. Filling Form State
279
- Update multiple form fields at once, preserving the dirty state:
280
-
281
- ````typescript
282
- form.fillState({
283
- name: 'John Doe',
284
- email: 'john@example.com'
285
- })
286
- ````
287
-
288
- ### 4. Synchronizing Values Without Marking Dirty
289
- Update both the current and original state, keeping the field "clean":
290
-
291
- ````typescript
292
- form.syncValue('email', 'new@example.com')
293
- ````
294
-
295
- ## Real-World Examples
296
- ### 1. Date/Time Handling
297
-
298
- ````typescript
299
- export class TimeTrackingEntryCreateUpdateForm extends BaseForm<RequestPayload, FormState> {
300
- protected override append: string[] = ['started_at', 'ended_at']
301
- protected override ignore: string[] = ['start_date', 'start_time', 'end_date', 'end_time']
302
-
303
- protected getStartedAt(): string {
304
- return DateTime.fromFormat(`${this.state.start_date} ${this.state.start_time}`, 'dd.MM.yyyy HH:mm').toISO()
305
- }
306
-
307
- protected getEndedAt(): string {
308
- return DateTime.fromFormat(`${this.state.end_date} ${this.state.end_time}`, 'dd.MM.yyyy HH:mm').toISO()
309
- }
310
- }
311
- ````
312
-
313
- ### 2. Complex Object Handling
314
-
315
- ````typescript
316
- export class IncomingVoucherCreateUpdateForm extends BaseForm<RequestPayload, FormState> {
317
- // Extract IDs from related objects
318
- protected getBusinessAssociateId(value: BusinessAssociateResource): string | null {
319
- return value?.id
320
- }
321
-
322
- protected getFileId(value: FileResource): string | null {
323
- return value?.id
324
- }
325
- }
326
- ````
Binary file
@@ -1,14 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en" class="h-full">
3
- <head>
4
- <meta charset="UTF-8">
5
- <title>Hank-IT UI</title>
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- </head>
8
- <body class="h-full">
9
-
10
- <div id="app" class="w-full h-full"></div>
11
-
12
- <script type="module" src="/js/app.js"></script>
13
- </body>
14
- </html>
@@ -1,8 +0,0 @@
1
- import { createApp } from 'vue'
2
- import App from './view/App.vue'
3
- import Router from './router'
4
-
5
- const app = createApp(App)
6
- .use(Router)
7
-
8
- app.mount('#app')
@@ -1,22 +0,0 @@
1
- import { createWebHistory, createRouter } from 'vue-router'
2
-
3
- const routes = [
4
- {
5
- path: '/pagination/:component?',
6
- component: () => import('@view/pagination/Pagination.vue'),
7
- name: 'pagination',
8
- props: true,
9
- },
10
- {
11
- path: '/requests/:component?',
12
- component: () => import('@view/requests/Requests.vue'),
13
- name: 'requests',
14
- props: true,
15
- }
16
- ]
17
-
18
-
19
- export default createRouter({
20
- history: createWebHistory(),
21
- routes, // short for `routes: routes`,
22
- })
@@ -1,49 +0,0 @@
1
- <template>
2
- <div class="container">
3
- <div class="sidebar">
4
- <ul>
5
- <li><RouterLink :to="{ name: 'requests' }">Requests</RouterLink></li>
6
- <li><RouterLink :to="{ name: 'pagination' }">Pagination</RouterLink></li>
7
- </ul>
8
- </div>
9
- <div class="content">
10
- <RouterView />
11
- </div>
12
- </div>
13
- </template>
14
-
15
- <script setup>
16
-
17
- </script>
18
-
19
- <style>
20
- body {
21
- margin: 0;
22
- padding:0;
23
- }
24
-
25
- .container {
26
- display: flex;
27
- flex-direction: row;
28
- }
29
-
30
- .sidebar,
31
- .content {
32
- display: flex;
33
- flex-direction: column;
34
- color: black;
35
- min-height: 500px;
36
- border-radius: 4px;
37
- margin: 10px;
38
- }
39
-
40
- .sidebar {
41
- flex-grow: 1;
42
- min-width: 300px;
43
- }
44
-
45
- .content {
46
- flex-grow: 5;
47
- min-width: 630px;
48
- }
49
- </style>
@@ -1,28 +0,0 @@
1
- <template>
2
- <select v-model="selectedComponentKey">
3
- <RouterLink
4
- v-for="(component, key) in components"
5
- :key="key"
6
- :to="component.route"
7
- custom
8
- v-slot="{ isActive, href, navigate }"
9
- >
10
- <option @click="navigate" :value="key">
11
- {{ component.name }}
12
- </option>
13
- </RouterLink>
14
- </select>
15
-
16
- <component v-if="selectedComponentKey" :is="components[selectedComponentKey].component" />
17
- </template>
18
-
19
- <script setup lang="ts">
20
- import {ref} from 'vue'
21
-
22
- const props = defineProps({
23
- components: {},
24
- component: String,
25
- })
26
-
27
- const selectedComponentKey = ref(props.component)
28
- </script>
@@ -1,28 +0,0 @@
1
- <template>
2
- <DemoPage :components="components" />
3
- </template>
4
-
5
- <script setup lang="ts">
6
- import TablePagination from './components/tablePagination/TablePagination.vue'
7
- import ErrorPagination from './components/errorPagination/ErrorPagination.vue'
8
- import InfiniteScrolling from './components/infiniteScrolling/InfiniteScrolling.vue'
9
- import DemoPage from '../layout/DemoPage.vue'
10
-
11
- const components = {
12
- 'table-pagination': {
13
- name: 'Paginated table',
14
- component: TablePagination,
15
- route: { name: 'pagination', params: { component: 'table-pagination' } },
16
- },
17
- 'error-pagination': {
18
- name: 'Pagination with error',
19
- component: ErrorPagination,
20
- route: { name: 'pagination', params: { component: 'error-pagination' } },
21
- },
22
- 'infinite-scrolling': {
23
- name: 'Infinite scrolling',
24
- component: InfiniteScrolling,
25
- route: { name: 'pagination', params: { component: 'infinite-scrolling' } },
26
- },
27
- }
28
- </script>
@@ -1,71 +0,0 @@
1
- <template>
2
- <table>
3
- <tr>
4
- <th>ID</th>
5
- <th>Title</th>
6
- <th>Description</th>
7
- </tr>
8
- <tr v-for="row in paginator.getPageData()">
9
- <td>{{ row.id }}</td>
10
- <td>{{ row.title }}</td>
11
- <td>{{ row.description }}</td>
12
- </tr>
13
- </table>
14
-
15
- Current page: {{ paginator.getCurrentPage() }}
16
- <br>
17
- Pages: {{ paginator.getPages() }}
18
- <br>
19
- Page Size: <input v-model="pageSize" />
20
- <br>
21
- Back Page <button @click="paginator.toPreviousPage()">Back</button>
22
- <br>
23
- Next Page <button @click="paginator.toNextPage()">Next</button>
24
- <br>
25
- Showing {{ paginator.getFromItemNumber() }} to {{ paginator.getToItemNumber() }} of {{ paginator.getTotal() }} items.
26
-
27
- {{ displayablePages }}
28
- </template>
29
-
30
- <script setup lang="ts">
31
- import {BaseRequest, FetchDriver, VueLoaderDriverFactory} from "@hank-it/ui/service/requests"
32
- import {Paginator, RequestDriver, VuePaginationDriverFactory} from "@hank-it/ui/service/pagination";
33
- import {getDisplayablePages} from '@hank-it/ui/service/helpers'
34
- import {GetProductsRequest} from "./GetProductsRequest";
35
- import {computed} from 'vue'
36
-
37
- /* Booting */
38
- BaseRequest.setRequestDriver(new FetchDriver)
39
- BaseRequest.setLoaderStateFactory(new VueLoaderDriverFactory)
40
- Paginator.setViewDriverFactory(new VuePaginationDriverFactory())
41
-
42
- /* component */
43
- const getProductsRequest = new GetProductsRequest
44
-
45
- const paginator = new Paginator(new RequestDriver(getProductsRequest))
46
-
47
- paginator.init(1, 10).catch(paginationErrorHandler)
48
-
49
- function paginationErrorHandler(response) {
50
- console.log(response.getError())
51
- }
52
-
53
- const pageSize = computed({
54
- set(value) {
55
- paginator.setPageSize(value)
56
- },
57
- get() {
58
- return paginator.getPageSize()
59
- }
60
- })
61
-
62
- const displayablePages = computed(() => {
63
- console.log(paginator.getPages())
64
-
65
- return getDisplayablePages(paginator.getPages().length, paginator.getCurrentPage())
66
- })
67
- </script>
68
-
69
- <style scoped>
70
-
71
- </style>
@@ -1,54 +0,0 @@
1
- import {BaseRequest, type Paginatable, JsonResponse } from '@hank-it/ui/service/requests'
2
- import type {PaginationResponseContract} from '@hank-it/ui/service/pagination'
3
-
4
- export interface ProductResource {
5
- id: number
6
- title: string
7
- description: string
8
- }
9
-
10
- export interface ProductPaginationResource {
11
- products: ProductResource[]
12
- total: number
13
- limit: number
14
- skip: number
15
- }
16
-
17
- export class GetProductsRequestResponse extends JsonResponse implements PaginationResponseContract {
18
- public getData() {
19
- return this.data
20
- }
21
-
22
- public getTotal(): number {
23
- return this.body.total
24
- }
25
-
26
- public dataHandler(data) {
27
- return data.products
28
- }
29
- }
30
-
31
- export class GetProductsRequest extends BaseRequest implements Paginatable {
32
- method() {
33
- return 'GET'
34
- }
35
-
36
- url() {
37
- return 'https://dummyjson.com/http/500'
38
- }
39
-
40
- public setPaginationParams(page: number, size: number): BaseRequest {
41
- return this.withParams({
42
- skip: (page - 1) * size,
43
- limit: size,
44
- })
45
- }
46
-
47
- public getCorsWithCredentials(): boolean {
48
- return false
49
- }
50
-
51
- protected getResponse() {
52
- return new GetProductsRequestResponse
53
- }
54
- }
@@ -1,50 +0,0 @@
1
- import {BaseRequest, type Paginatable, JsonResponse } from '@hank-it/ui/service/requests'
2
- import type {PaginationResponseContract} from '@hank-it/ui/service/pagination'
3
-
4
- export interface ProductResource {
5
- id: number
6
- title: string
7
- description: string
8
- }
9
-
10
- export interface ProductPaginationResource {
11
- products: ProductResource[]
12
- total: number
13
- limit: number
14
- skip: number
15
- }
16
-
17
- export class GetProductsRequestResponse extends JsonResponse implements PaginationResponseContract {
18
- public getData() {
19
- return this.data
20
- }
21
-
22
- public getTotal(): number {
23
- return this.body.total
24
- }
25
-
26
- public dataHandler(data) {
27
- return data.products
28
- }
29
- }
30
-
31
- export class GetProductsRequest extends BaseRequest implements Paginatable {
32
- method() {
33
- return 'GET'
34
- }
35
-
36
- url() {
37
- return 'https://dummyjson.com/products'
38
- }
39
-
40
- public setPaginationParams(page: number, size: number): BaseRequest {
41
- return this.withParams({
42
- skip: (page - 1) * size,
43
- limit: size,
44
- })
45
- }
46
-
47
- protected getResponse() {
48
- return new GetProductsRequestResponse
49
- }
50
- }