@dynamic-field-kit/angular 1.4.0 → 1.5.0
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/CHANGELOG.md +166 -0
- package/LICENSE +21 -0
- package/README.md +144 -5
- package/dist/components/DynamicFormDevTools.d.ts +16 -0
- package/dist/components/DynamicInput.d.ts +2 -1
- package/dist/components/FieldInput.d.ts +7 -1
- package/dist/components/MultiFieldInput.d.ts +13 -2
- package/dist/fesm2022/dynamic-field-kit-angular.mjs +578 -34
- package/dist/index.d.ts +1 -1
- package/dist/layout/index.d.ts +2 -2
- package/dist/lib/dynamic-field-kit.module.d.ts +4 -4
- package/dist/lib/dynamic-form.store.d.ts +23 -0
- package/dist/public-api.d.ts +10 -8
- package/package.json +40 -21
- package/dist/README.md +0 -235
- package/dist/esm2022/components/BaseInput.mjs +0 -59
- package/dist/esm2022/components/DynamicInput.mjs +0 -244
- package/dist/esm2022/components/FieldInput.mjs +0 -99
- package/dist/esm2022/components/MultiFieldInput.mjs +0 -338
- package/dist/esm2022/dynamic-field-kit-angular.mjs +0 -5
- package/dist/esm2022/fieldRegistryToken.mjs +0 -12
- package/dist/esm2022/layout/defaultLayouts.mjs +0 -114
- package/dist/esm2022/layout/index.mjs +0 -3
- package/dist/esm2022/layout/layoutRegistry.mjs +0 -14
- package/dist/esm2022/lib/dynamic-field-kit.module.mjs +0 -52
- package/dist/esm2022/public-api.mjs +0 -18
- package/dist/esm2022/types/layout.mjs +0 -2
- package/dist/fesm2022/dynamic-field-kit-angular.mjs.map +0 -1
- package/ng-package.json +0 -7
- package/src/components/BaseInput.ts +0 -57
- package/src/components/DynamicInput.ts +0 -280
- package/src/components/FieldInput.ts +0 -74
- package/src/components/MultiFieldInput.ts +0 -331
- package/src/fieldRegistryToken.ts +0 -15
- package/src/layout/defaultLayouts.ts +0 -70
- package/src/layout/index.ts +0 -2
- package/src/layout/layoutRegistry.ts +0 -25
- package/src/lib/dynamic-field-kit.module.ts +0 -29
- package/src/public-api.ts +0 -40
- package/src/types/layout.ts +0 -14
- package/test/DynamicInput.spec.ts +0 -230
- package/test/FieldInput.spec.ts +0 -146
- package/test/MultiFieldInput.spec.ts +0 -256
- package/test/helpers/renderers.ts +0 -89
- package/test/layout.spec.ts +0 -119
- package/test/publicApi.spec.ts +0 -64
- package/test/setup.ts +0 -12
- package/test/smoke.spec.ts +0 -27
- package/tsconfig.json +0 -13
- package/tsconfig.spec.json +0 -9
- package/vitest.config.ts +0 -30
package/dist/index.d.ts
CHANGED
package/dist/layout/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './defaultLayouts';
|
|
2
|
-
export { layoutRegistry, LayoutRegistry } from './layoutRegistry';
|
|
1
|
+
export * from './defaultLayouts.js';
|
|
2
|
+
export { layoutRegistry, LayoutRegistry } from './layoutRegistry.js';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as i0 from "@angular/core";
|
|
2
2
|
import * as i1 from "@angular/common";
|
|
3
|
-
import * as i2 from "../components/DynamicInput";
|
|
4
|
-
import * as i3 from "../components/FieldInput";
|
|
5
|
-
import * as i4 from "../components/MultiFieldInput";
|
|
6
|
-
import * as i5 from "../layout/defaultLayouts";
|
|
3
|
+
import * as i2 from "../components/DynamicInput.js";
|
|
4
|
+
import * as i3 from "../components/FieldInput.js";
|
|
5
|
+
import * as i4 from "../components/MultiFieldInput.js";
|
|
6
|
+
import * as i5 from "../layout/defaultLayouts.js";
|
|
7
7
|
export declare class DynamicFieldKitModule {
|
|
8
8
|
static ɵfac: i0.ɵɵFactoryDeclaration<DynamicFieldKitModule, never>;
|
|
9
9
|
static ɵmod: i0.ɵɵNgModuleDeclaration<DynamicFieldKitModule, never, [typeof i1.CommonModule, typeof i2.DynamicInput, typeof i3.FieldInput, typeof i4.MultiFieldInput, typeof i5.ColumnLayout, typeof i5.RowLayout, typeof i5.GridLayout], [typeof i2.DynamicInput, typeof i3.FieldInput, typeof i4.MultiFieldInput, typeof i5.ColumnLayout, typeof i5.RowLayout, typeof i5.GridLayout]>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FieldDescription, Properties } from '@dynamic-field-kit/core';
|
|
2
|
+
export interface DynamicFormOptions {
|
|
3
|
+
fields: FieldDescription[];
|
|
4
|
+
initialValues?: Properties;
|
|
5
|
+
validateOnBlur?: boolean;
|
|
6
|
+
validateOnChange?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function createDynamicFormStore(options: DynamicFormOptions): {
|
|
9
|
+
data: import("@angular/core").WritableSignal<Properties>;
|
|
10
|
+
errors: import("@angular/core").WritableSignal<Record<string, string[]>>;
|
|
11
|
+
isValid: import("@angular/core").Signal<boolean>;
|
|
12
|
+
isDirty: import("@angular/core").WritableSignal<boolean>;
|
|
13
|
+
touched: import("@angular/core").WritableSignal<Record<string, boolean>>;
|
|
14
|
+
isSubmitting: import("@angular/core").WritableSignal<boolean>;
|
|
15
|
+
isSubmitted: import("@angular/core").WritableSignal<boolean>;
|
|
16
|
+
setFieldValue: (name: string, value: unknown) => void;
|
|
17
|
+
setFieldTouched: (name: string, isTouched?: boolean) => void;
|
|
18
|
+
handleChange: (newData: Properties) => void;
|
|
19
|
+
handleBlur: (fieldName: string) => void;
|
|
20
|
+
reset: (newValues?: Properties) => void;
|
|
21
|
+
validate: () => boolean;
|
|
22
|
+
handleSubmit: (onValid: (data: Properties) => void | Promise<void>, onInvalid?: (errors: Record<string, string[]>) => void) => (e?: Event) => Promise<void>;
|
|
23
|
+
};
|
package/dist/public-api.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
export * from './components/BaseInput';
|
|
2
|
-
export * from './components/DynamicInput';
|
|
3
|
-
export * from './components/FieldInput';
|
|
4
|
-
export * from './components/MultiFieldInput';
|
|
5
|
-
export * from './
|
|
6
|
-
export * from './
|
|
7
|
-
export * from './
|
|
1
|
+
export * from './components/BaseInput.js';
|
|
2
|
+
export * from './components/DynamicInput.js';
|
|
3
|
+
export * from './components/FieldInput.js';
|
|
4
|
+
export * from './components/MultiFieldInput.js';
|
|
5
|
+
export * from './components/DynamicFormDevTools.js';
|
|
6
|
+
export * from './lib/dynamic-form.store.js';
|
|
7
|
+
export * from './layout/index.js';
|
|
8
|
+
export * from './types/layout.js';
|
|
9
|
+
export * from './lib/dynamic-field-kit.module.js';
|
|
8
10
|
export type { FieldDescription, FieldRendererProps, FieldTypeKey, } from '@dynamic-field-kit/core';
|
|
9
11
|
export { fieldRegistry, FieldRegistry } from '@dynamic-field-kit/core';
|
|
10
12
|
export { validateField, validateFieldAsync, validateFields, validateFieldsAsync, resolveDisabled, resolveReadOnly, resolveOptions, validators, } from '@dynamic-field-kit/core';
|
|
11
13
|
export type { ValidationResult } from '@dynamic-field-kit/core';
|
|
12
|
-
export { FIELD_REGISTRY } from './fieldRegistryToken';
|
|
14
|
+
export { FIELD_REGISTRY } from './fieldRegistryToken.js';
|
package/package.json
CHANGED
|
@@ -1,36 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-field-kit/angular",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Angular renderer for dynamic-field-kit",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
7
7
|
"type": "module",
|
|
8
|
-
"sideEffects":
|
|
8
|
+
"sideEffects": [
|
|
9
|
+
"**/fesm2022/*.mjs"
|
|
10
|
+
],
|
|
9
11
|
"main": "dist/fesm2022/dynamic-field-kit-angular.mjs",
|
|
10
12
|
"module": "dist/fesm2022/dynamic-field-kit-angular.mjs",
|
|
11
13
|
"types": "dist/index.d.ts",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"!dist/README.md",
|
|
17
|
+
"!dist/LICENSE",
|
|
18
|
+
"CHANGELOG.md"
|
|
19
|
+
],
|
|
12
20
|
"peerDependencies": {
|
|
13
|
-
"@angular/common": ">=
|
|
14
|
-
"@angular/core": ">=
|
|
21
|
+
"@angular/common": ">=14 <22",
|
|
22
|
+
"@angular/core": ">=14 <22",
|
|
15
23
|
"@dynamic-field-kit/core": "^1.3.0"
|
|
16
24
|
},
|
|
17
25
|
"publishConfig": {
|
|
18
|
-
"access": "public"
|
|
26
|
+
"access": "public",
|
|
27
|
+
"provenance": true
|
|
19
28
|
},
|
|
20
29
|
"scripts": {
|
|
21
30
|
"build": "ng-packagr -p ng-package.json",
|
|
31
|
+
"postbuild": "node ../../scripts/strip-sourcemaps.js dist && node ../../scripts/add-dts-extensions.js dist",
|
|
22
32
|
"clean": "rimraf dist coverage",
|
|
23
33
|
"prepublishOnly": "npm run build",
|
|
24
34
|
"test": "vitest run",
|
|
25
|
-
"
|
|
26
|
-
"release:patch": "npm version patch && npm run build && npm run publish:dist",
|
|
27
|
-
"release:minor": "npm version minor && npm run build && npm run publish:dist",
|
|
28
|
-
"release:major": "npm version major && npm run build && npm run publish:dist",
|
|
29
|
-
"lint": "echo \"skip lint for Angular\""
|
|
35
|
+
"lint": "eslint ."
|
|
30
36
|
},
|
|
31
37
|
"devDependencies": {
|
|
32
|
-
"@analogjs/vite-plugin-angular": "^
|
|
33
|
-
"@analogjs/vitest-angular": "^
|
|
38
|
+
"@analogjs/vite-plugin-angular": "^2.7.1",
|
|
39
|
+
"@analogjs/vitest-angular": "^2.7.1",
|
|
34
40
|
"@angular-devkit/build-angular": "^19.2.27",
|
|
35
41
|
"@angular/cdk": "^19.0.0",
|
|
36
42
|
"@angular/common": "^19.0.0",
|
|
@@ -40,24 +46,37 @@
|
|
|
40
46
|
"@angular/forms": "^19.0.0",
|
|
41
47
|
"@angular/platform-browser": "^19.0.0",
|
|
42
48
|
"@angular/platform-browser-dynamic": "^19.0.0",
|
|
43
|
-
"@dynamic-field-kit/core": "^1.
|
|
44
|
-
"@vitest/coverage-istanbul": "^1.
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"ng-packagr": "^17.3.0",
|
|
49
|
+
"@dynamic-field-kit/core": "^1.5.0",
|
|
50
|
+
"@vitest/coverage-istanbul": "^4.1.11",
|
|
51
|
+
"jsdom": "^29.1.1",
|
|
52
|
+
"ng-packagr": "^19.2.2",
|
|
48
53
|
"rimraf": "^6.1.3",
|
|
49
54
|
"rxjs": "^7.8.0",
|
|
50
|
-
"typescript": "~5.
|
|
51
|
-
"vitest": "^1.
|
|
55
|
+
"typescript": "~5.8.3",
|
|
56
|
+
"vitest": "^4.1.11",
|
|
52
57
|
"zone.js": "^0.15.0"
|
|
53
58
|
},
|
|
54
59
|
"repository": {
|
|
55
60
|
"type": "git",
|
|
56
|
-
"url": "git+https://github.com/vannt-dev/dynamic-field-kit.git"
|
|
61
|
+
"url": "git+https://github.com/vannt-dev/dynamic-field-kit.git",
|
|
62
|
+
"directory": "packages/angular"
|
|
57
63
|
},
|
|
58
64
|
"keywords": [
|
|
59
65
|
"dynamic-field",
|
|
60
66
|
"dynamic-field-kit",
|
|
61
67
|
"dynamic-field-kit/angular"
|
|
62
|
-
]
|
|
68
|
+
],
|
|
69
|
+
"homepage": "https://github.com/vannt-dev/dynamic-field-kit/tree/develop/packages/angular#readme",
|
|
70
|
+
"bugs": {
|
|
71
|
+
"url": "https://github.com/vannt-dev/dynamic-field-kit/issues"
|
|
72
|
+
},
|
|
73
|
+
"exports": {
|
|
74
|
+
".": {
|
|
75
|
+
"types": "./dist/index.d.ts",
|
|
76
|
+
"default": "./dist/fesm2022/dynamic-field-kit-angular.mjs"
|
|
77
|
+
},
|
|
78
|
+
"./package.json": {
|
|
79
|
+
"default": "./package.json"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
63
82
|
}
|
package/dist/README.md
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
# @dynamic-field-kit/angular
|
|
2
|
-
|
|
3
|
-
Angular adapter for `@dynamic-field-kit/core`.
|
|
4
|
-
|
|
5
|
-
This package provides Angular components and a convenience module that render field schemas defined with `@dynamic-field-kit/core`.
|
|
6
|
-
|
|
7
|
-
Demo app: https://github.com/vannt-dev/dynamic-field-kit-demo
|
|
8
|
-
|
|
9
|
-
## Install
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
npm install @dynamic-field-kit/core @dynamic-field-kit/angular
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Note: `@dynamic-field-kit/core`, `@angular/core`, and `@angular/common` are **peer dependencies** — this adapter does not bundle or auto-install them, so add them to your app explicitly (as shown above). Keep a single `@dynamic-field-kit/core` version across all adapters so they share one registry.
|
|
16
|
-
|
|
17
|
-
If you need to pin versions explicitly:
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
npm install @dynamic-field-kit/core@^1.0.12 @dynamic-field-kit/angular@^1.2.3
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## What it exports
|
|
24
|
-
|
|
25
|
-
- `DynamicInput`
|
|
26
|
-
- `FieldInput`
|
|
27
|
-
- `MultiFieldInput`
|
|
28
|
-
- `DynamicFieldKitModule`
|
|
29
|
-
- `fieldRegistry`
|
|
30
|
-
- `FieldRegistry` (class, for scoped registries)
|
|
31
|
-
- `FIELD_REGISTRY` (injection token)
|
|
32
|
-
- `validateField` / `validateFields` / `resolveDisabled` / `resolveReadOnly` / `ValidationResult`
|
|
33
|
-
|
|
34
|
-
## Basic setup (Angular 19+)
|
|
35
|
-
|
|
36
|
-
1. Import the component and register fields before bootstrap.
|
|
37
|
-
|
|
38
|
-
```ts
|
|
39
|
-
import 'zone.js';
|
|
40
|
-
import { bootstrapApplication } from '@angular/platform-browser';
|
|
41
|
-
import { fieldRegistry } from '@dynamic-field-kit/angular';
|
|
42
|
-
import { AppComponent } from './app/app.component';
|
|
43
|
-
import { TextFieldComponent } from './app/components/text-field.component';
|
|
44
|
-
import { NumberFieldComponent } from './app/components/number-field.component';
|
|
45
|
-
|
|
46
|
-
fieldRegistry.register('text', TextFieldComponent as any);
|
|
47
|
-
fieldRegistry.register('number', NumberFieldComponent as any);
|
|
48
|
-
|
|
49
|
-
bootstrapApplication(AppComponent, {
|
|
50
|
-
providers: [],
|
|
51
|
-
}).catch((err) => console.error(err));
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
2. Use the component in a standalone component.
|
|
55
|
-
|
|
56
|
-
```ts
|
|
57
|
-
import { Component } from '@angular/core';
|
|
58
|
-
import { CommonModule } from '@angular/common';
|
|
59
|
-
import { FieldDescription } from '@dynamic-field-kit/core';
|
|
60
|
-
import { MultiFieldInput } from '@dynamic-field-kit/angular';
|
|
61
|
-
|
|
62
|
-
@Component({
|
|
63
|
-
selector: 'app-root',
|
|
64
|
-
standalone: true,
|
|
65
|
-
imports: [CommonModule, MultiFieldInput],
|
|
66
|
-
templateUrl: './app.component.html',
|
|
67
|
-
})
|
|
68
|
-
export class AppComponent {
|
|
69
|
-
fields: FieldDescription[] = [
|
|
70
|
-
{ name: 'name', type: 'text', label: 'Name' },
|
|
71
|
-
{ name: 'age', type: 'number', label: 'Age' },
|
|
72
|
-
];
|
|
73
|
-
|
|
74
|
-
data: any = {};
|
|
75
|
-
|
|
76
|
-
onChange(data: any) {
|
|
77
|
-
this.data = data;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
3. Render your schema in a template.
|
|
83
|
-
|
|
84
|
-
```html
|
|
85
|
-
<dfk-multi-field-input
|
|
86
|
-
[fieldDescriptions]="fields"
|
|
87
|
-
[properties]="data"
|
|
88
|
-
(onChange)="onChange($event)"
|
|
89
|
-
></dfk-multi-field-input>
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## Layouts
|
|
93
|
-
|
|
94
|
-
`MultiFieldInput` supports `column`, `row`, `grid`, and `responsive` (mobile/desktop with a custom breakpoint), matching the React and Vue adapters:
|
|
95
|
-
|
|
96
|
-
```html
|
|
97
|
-
<dfk-multi-field-input
|
|
98
|
-
[fieldDescriptions]="fields"
|
|
99
|
-
[layout]="{ type: 'grid', columns: 3, gap: 16 }"
|
|
100
|
-
></dfk-multi-field-input>
|
|
101
|
-
|
|
102
|
-
<dfk-multi-field-input
|
|
103
|
-
[fieldDescriptions]="fields"
|
|
104
|
-
[layout]="{
|
|
105
|
-
type: 'responsive',
|
|
106
|
-
mobile: 'column',
|
|
107
|
-
desktop: { type: 'grid', columns: 2, gap: 12 }
|
|
108
|
-
}"
|
|
109
|
-
></dfk-multi-field-input>
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
## Derived fields with `computeValue`
|
|
113
|
-
|
|
114
|
-
Give a field a `computeValue` to derive its value from the rest of the form data whenever any field changes:
|
|
115
|
-
|
|
116
|
-
```ts
|
|
117
|
-
fields: FieldDescription[] = [
|
|
118
|
-
{ name: 'firstName', type: 'text' },
|
|
119
|
-
{ name: 'lastName', type: 'text' },
|
|
120
|
-
{
|
|
121
|
-
name: 'fullName',
|
|
122
|
-
type: 'text',
|
|
123
|
-
computeValue: (data) => `${data.firstName ?? ''} ${data.lastName ?? ''}`.trim(),
|
|
124
|
-
},
|
|
125
|
-
];
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## Validation & conditions
|
|
129
|
-
|
|
130
|
-
Declare a `validate` hook and dynamic `disabledCondition`/`readOnlyCondition`;
|
|
131
|
-
your renderer component receives `error`, `disabled`, and `readOnly` inputs, and
|
|
132
|
-
`dfk-multi-field-input` emits `(validityChange)`:
|
|
133
|
-
|
|
134
|
-
```html
|
|
135
|
-
<dfk-multi-field-input
|
|
136
|
-
[fieldDescriptions]="fields"
|
|
137
|
-
[properties]="data"
|
|
138
|
-
(onChange)="onChange($event)"
|
|
139
|
-
(validityChange)="canSubmit = $event.valid"
|
|
140
|
-
></dfk-multi-field-input>
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
For submit-time whole-form validation, call `validateFields(fields, data)`.
|
|
144
|
-
|
|
145
|
-
## Repeatable field groups
|
|
146
|
-
|
|
147
|
-
A field with `fields` renders as a repeatable group: `data[name]` becomes an array of items, each shaped by the nested `fields`, with "Add"/"Remove" controls rendered automatically.
|
|
148
|
-
|
|
149
|
-
```ts
|
|
150
|
-
fields: FieldDescription[] = [
|
|
151
|
-
{
|
|
152
|
-
name: 'contacts',
|
|
153
|
-
type: 'group',
|
|
154
|
-
label: 'Contacts',
|
|
155
|
-
fields: [
|
|
156
|
-
{ name: 'email', type: 'text', label: 'Email' },
|
|
157
|
-
{ name: 'phone', type: 'text', label: 'Phone' },
|
|
158
|
-
],
|
|
159
|
-
defaultItem: { email: '', phone: '' },
|
|
160
|
-
keyField: 'id', // optional: stable trackBy key instead of the array index
|
|
161
|
-
minItems: 1,
|
|
162
|
-
maxItems: 5,
|
|
163
|
-
},
|
|
164
|
-
];
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
```html
|
|
168
|
-
<dfk-multi-field-input [fieldDescriptions]="fields"></dfk-multi-field-input>
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
## Scoped registries
|
|
172
|
-
|
|
173
|
-
`fieldRegistry` is a process-wide singleton. To give a component or route its own renderers, provide the `FIELD_REGISTRY` token with an isolated `FieldRegistry`. Components without an override keep using the global singleton.
|
|
174
|
-
|
|
175
|
-
```ts
|
|
176
|
-
import { FieldRegistry, FIELD_REGISTRY } from '@dynamic-field-kit/angular';
|
|
177
|
-
|
|
178
|
-
const registry = new FieldRegistry();
|
|
179
|
-
registry.register('text', TextFieldComponent as any);
|
|
180
|
-
|
|
181
|
-
@Component({
|
|
182
|
-
selector: 'app-scoped-form',
|
|
183
|
-
standalone: true,
|
|
184
|
-
imports: [MultiFieldInput],
|
|
185
|
-
providers: [{ provide: FIELD_REGISTRY, useValue: registry }],
|
|
186
|
-
template: `<dfk-multi-field-input [fieldDescriptions]="fields" />`,
|
|
187
|
-
})
|
|
188
|
-
export class ScopedFormComponent {}
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
## Passing renderer-specific props
|
|
192
|
-
|
|
193
|
-
The generic adapter forwards only the shared `FieldRendererProps`. For inputs specific to one renderer (e.g. `acceptFile`, `maxLength`), pass them per field via `FieldDescription.props`; they are set on the renderer instance verbatim.
|
|
194
|
-
|
|
195
|
-
```ts
|
|
196
|
-
{ name: 'avatar', type: 'file', props: { acceptFile: 'image/*' } }
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
## Legacy setup (Angular 14 and earlier with NgModule)
|
|
200
|
-
|
|
201
|
-
```ts
|
|
202
|
-
import { BrowserModule } from '@angular/platform-browser';
|
|
203
|
-
import { NgModule } from '@angular/core';
|
|
204
|
-
import { DynamicFieldKitModule } from '@dynamic-field-kit/angular';
|
|
205
|
-
|
|
206
|
-
@NgModule({
|
|
207
|
-
imports: [BrowserModule, DynamicFieldKitModule],
|
|
208
|
-
})
|
|
209
|
-
export class AppModule {}
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
## Type augmentation
|
|
213
|
-
|
|
214
|
-
```ts
|
|
215
|
-
import '@dynamic-field-kit/core';
|
|
216
|
-
|
|
217
|
-
declare module '@dynamic-field-kit/core' {
|
|
218
|
-
interface FieldTypeMap {
|
|
219
|
-
text: string;
|
|
220
|
-
number: number;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
## Notes
|
|
226
|
-
|
|
227
|
-
- Register Angular component classes in `fieldRegistry`.
|
|
228
|
-
- Do not register React or Vue renderers in the Angular adapter.
|
|
229
|
-
- `MultiFieldInput` supports `column`, `row`, `grid`, and `responsive` layouts, and derives fields using `computeValue`.
|
|
230
|
-
- Fields with `fields` render as repeatable groups instead of going through `fieldRegistry`.
|
|
231
|
-
- The shared schema and field types still come from `@dynamic-field-kit/core`.
|
|
232
|
-
|
|
233
|
-
## License
|
|
234
|
-
|
|
235
|
-
MIT
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { Component, EventEmitter, Input, Output, } from '@angular/core';
|
|
2
|
-
import * as i0 from "@angular/core";
|
|
3
|
-
export class BaseInputComponent {
|
|
4
|
-
cdr;
|
|
5
|
-
value;
|
|
6
|
-
label;
|
|
7
|
-
placeholder;
|
|
8
|
-
required;
|
|
9
|
-
disabled;
|
|
10
|
-
readOnly;
|
|
11
|
-
error;
|
|
12
|
-
options;
|
|
13
|
-
className;
|
|
14
|
-
description;
|
|
15
|
-
valueChange = new EventEmitter();
|
|
16
|
-
constructor(cdr) {
|
|
17
|
-
this.cdr = cdr;
|
|
18
|
-
}
|
|
19
|
-
ngOnChanges(_changes) {
|
|
20
|
-
this.detectChanges();
|
|
21
|
-
}
|
|
22
|
-
detectChanges() {
|
|
23
|
-
this.cdr.markForCheck();
|
|
24
|
-
}
|
|
25
|
-
hasChanges(changes, prop) {
|
|
26
|
-
return changes[prop] !== undefined;
|
|
27
|
-
}
|
|
28
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: BaseInputComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
29
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: BaseInputComponent, isStandalone: true, selector: "ng-component", inputs: { value: "value", label: "label", placeholder: "placeholder", required: "required", disabled: "disabled", readOnly: "readOnly", error: "error", options: "options", className: "className", description: "description" }, outputs: { valueChange: "valueChange" }, usesOnChanges: true, ngImport: i0, template: '', isInline: true });
|
|
30
|
-
}
|
|
31
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: BaseInputComponent, decorators: [{
|
|
32
|
-
type: Component,
|
|
33
|
-
args: [{
|
|
34
|
-
template: '',
|
|
35
|
-
}]
|
|
36
|
-
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { value: [{
|
|
37
|
-
type: Input
|
|
38
|
-
}], label: [{
|
|
39
|
-
type: Input
|
|
40
|
-
}], placeholder: [{
|
|
41
|
-
type: Input
|
|
42
|
-
}], required: [{
|
|
43
|
-
type: Input
|
|
44
|
-
}], disabled: [{
|
|
45
|
-
type: Input
|
|
46
|
-
}], readOnly: [{
|
|
47
|
-
type: Input
|
|
48
|
-
}], error: [{
|
|
49
|
-
type: Input
|
|
50
|
-
}], options: [{
|
|
51
|
-
type: Input
|
|
52
|
-
}], className: [{
|
|
53
|
-
type: Input
|
|
54
|
-
}], description: [{
|
|
55
|
-
type: Input
|
|
56
|
-
}], valueChange: [{
|
|
57
|
-
type: Output
|
|
58
|
-
}] } });
|
|
59
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQmFzZUlucHV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvQmFzZUlucHV0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFFTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFFTCxNQUFNLEdBRVAsTUFBTSxlQUFlLENBQUM7O0FBcUJ2QixNQUFNLE9BQWdCLGtCQUFrQjtJQWNoQjtJQWJiLEtBQUssQ0FBVztJQUNoQixLQUFLLENBQVU7SUFDZixXQUFXLENBQVU7SUFDckIsUUFBUSxDQUFXO0lBQ25CLFFBQVEsQ0FBVztJQUNuQixRQUFRLENBQVc7SUFDbkIsS0FBSyxDQUFxQjtJQUMxQixPQUFPLENBQWE7SUFDcEIsU0FBUyxDQUFVO0lBQ25CLFdBQVcsQ0FBVTtJQUVwQixXQUFXLEdBQUcsSUFBSSxZQUFZLEVBQVcsQ0FBQztJQUVwRCxZQUFzQixHQUFzQjtRQUF0QixRQUFHLEdBQUgsR0FBRyxDQUFtQjtJQUFHLENBQUM7SUFFaEQsV0FBVyxDQUFDLFFBQXVCO1FBQ2pDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUN2QixDQUFDO0lBRVMsYUFBYTtRQUNyQixJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFUyxVQUFVLENBQUMsT0FBc0IsRUFBRSxJQUFZO1FBQ3ZELE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLFNBQVMsQ0FBQztJQUNyQyxDQUFDO3dHQTFCbUIsa0JBQWtCOzRGQUFsQixrQkFBa0Isd1dBRjVCLEVBQUU7OzRGQUVRLGtCQUFrQjtrQkFIdkMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsRUFBRTtpQkFDYjtzRkFFVSxLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csS0FBSztzQkFBYixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csS0FBSztzQkFBYixLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFDRyxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBRUksV0FBVztzQkFBcEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT3V0cHV0LFxuICBTaW1wbGVDaGFuZ2VzLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuLy8gTWlycm9ycyB0aGUgZnJhbWV3b3JrLWFnbm9zdGljIEZpZWxkUmVuZGVyZXJQcm9wcy4gRG9tYWluLXNwZWNpZmljIGlucHV0c1xuLy8gKGFjY2VwdEZpbGUsIG1heExlbmd0aCwgLi4uKSBpbnRlbnRpb25hbGx5IGxpdmUgb24gdGhlIGluZGl2aWR1YWwgcmVuZGVyZXIsXG4vLyBub3QgaGVyZSAtIHBhc3MgdGhlbSBwZXIgZmllbGQgdmlhIEZpZWxkRGVzY3JpcHRpb24ucHJvcHMgaW5zdGVhZC5cbmV4cG9ydCBpbnRlcmZhY2UgRmllbGRJbnB1dFByb3BzIHtcbiAgdmFsdWU/OiB1bmtub3duO1xuICBsYWJlbD86IHN0cmluZztcbiAgcGxhY2Vob2xkZXI/OiBzdHJpbmc7XG4gIHJlcXVpcmVkPzogYm9vbGVhbjtcbiAgZGlzYWJsZWQ/OiBib29sZWFuO1xuICByZWFkT25seT86IGJvb2xlYW47XG4gIGVycm9yPzogc3RyaW5nIHwgc3RyaW5nW107XG4gIG9wdGlvbnM/OiB1bmtub3duW107XG4gIGNsYXNzTmFtZT86IHN0cmluZztcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG59XG5cbkBDb21wb25lbnQoe1xuICB0ZW1wbGF0ZTogJycsXG59KVxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VJbnB1dENvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcyB7XG4gIEBJbnB1dCgpIHZhbHVlPzogdW5rbm93bjtcbiAgQElucHV0KCkgbGFiZWw/OiBzdHJpbmc7XG4gIEBJbnB1dCgpIHBsYWNlaG9sZGVyPzogc3RyaW5nO1xuICBASW5wdXQoKSByZXF1aXJlZD86IGJvb2xlYW47XG4gIEBJbnB1dCgpIGRpc2FibGVkPzogYm9vbGVhbjtcbiAgQElucHV0KCkgcmVhZE9ubHk/OiBib29sZWFuO1xuICBASW5wdXQoKSBlcnJvcj86IHN0cmluZyB8IHN0cmluZ1tdO1xuICBASW5wdXQoKSBvcHRpb25zPzogdW5rbm93bltdO1xuICBASW5wdXQoKSBjbGFzc05hbWU/OiBzdHJpbmc7XG4gIEBJbnB1dCgpIGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuXG4gIEBPdXRwdXQoKSB2YWx1ZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8dW5rbm93bj4oKTtcblxuICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZikge31cblxuICBuZ09uQ2hhbmdlcyhfY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIHRoaXMuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGRldGVjdENoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgaGFzQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzLCBwcm9wOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gY2hhbmdlc1twcm9wXSAhPT0gdW5kZWZpbmVkO1xuICB9XG59XG4iXX0=
|