0
# Services
1
2
Core services for configuration management, form building, and dynamic field generation in NGX-Formly.
3
4
## Capabilities
5
6
### FormlyConfig
7
8
Injectable service for managing global Formly configuration including field types, validators, wrappers, and extensions.
9
10
```typescript { .api }
11
/**
12
* Service for managing global Formly configuration
13
*/
14
@Injectable({ providedIn: 'root' })
15
export class FormlyConfig {
16
/** Extra configuration options */
17
extras: FormlyConfigExtras;
18
19
/**
20
* Add configuration options to the global configuration
21
* @param config - Configuration options to add
22
*/
23
addConfig(config: ConfigOption): void;
24
25
/**
26
* Register field type(s) with the configuration system
27
* @param options - Field type configuration or array of configurations
28
*/
29
setType(options: TypeOption | TypeOption[]): void;
30
31
/**
32
* Register wrapper(s) with the configuration system
33
* @param options - Wrapper configuration or array of configurations
34
*/
35
setWrapper(options: WrapperOption | WrapperOption[]): void;
36
37
/**
38
* Register validator(s) with the configuration system
39
* @param options - Validator configuration or array of configurations
40
*/
41
setValidator(options: ValidatorOption | ValidatorOption[]): void;
42
43
/**
44
* Register validation message(s) with the configuration system
45
* @param options - Validation message configuration or array of configurations
46
*/
47
setValidationMessage(options: ValidationMessageOption | ValidationMessageOption[]): void;
48
49
/**
50
* Get field type configuration by name
51
* @param name - Name of the field type or component type
52
* @param throwIfNotFound - Whether to throw error if type not found
53
* @returns Field type configuration
54
*/
55
getType(name: FormlyFieldConfig['type'], throwIfNotFound?: boolean): TypeOption;
56
57
/**
58
* Get validator configuration by name
59
* @param name - Name of the validator
60
* @returns Validator configuration
61
*/
62
getValidator(name: string): ValidatorOption;
63
64
/**
65
* Get wrapper configuration by name
66
* @param name - Name of the wrapper or wrapper component type
67
* @returns Wrapper configuration
68
*/
69
getWrapper(name: string | Type<FieldWrapper>): WrapperOption;
70
71
/**
72
* Add validation message for a specific validator
73
* @param name - Name of the validator
74
* @param message - Message string or function
75
*/
76
addValidatorMessage(name: string, message: ValidationMessageOption['message']): void;
77
78
/**
79
* Get validation message by validator name
80
* @param name - Name of the validator
81
* @returns Validation message
82
*/
83
getValidatorMessage(name: string): ValidationMessageOption['message'];
84
85
/** Map of registered field types */
86
types: { [name: string]: TypeOption };
87
88
/** Map of registered validators */
89
validators: { [name: string]: ValidatorOption };
90
91
/** Map of registered wrappers */
92
wrappers: { [name: string]: WrapperOption };
93
94
/** Map of registered validation messages */
95
messages: { [name: string]: ValidationMessageOption['message'] };
96
97
/** Map of registered extensions */
98
extensions: { [name: string]: FormlyExtension };
99
}
100
```
101
102
**Usage Example:**
103
104
```typescript
105
import { Injectable, Component } from '@angular/core';
106
import { FormlyConfig, FieldType } from '@ngx-formly/core';
107
108
@Component({
109
selector: 'custom-input',
110
template: `<input [formControl]="formControl" [formlyAttributes]="field">`
111
})
112
export class CustomInputComponent extends FieldType {}
113
114
@Injectable()
115
export class MyConfigService {
116
constructor(private formlyConfig: FormlyConfig) {
117
this.setupConfiguration();
118
}
119
120
private setupConfiguration() {
121
// Register custom field type
122
this.formlyConfig.setType({
123
name: 'custom-input',
124
component: CustomInputComponent,
125
wrappers: ['form-field']
126
});
127
128
// Register custom validator
129
this.formlyConfig.setValidator({
130
name: 'custom-validator',
131
validation: (control) => {
132
return control.value && control.value.length > 5 ? null : { customValidator: true };
133
}
134
});
135
136
// Register validation message
137
this.formlyConfig.setValidationMessage({
138
name: 'custom-validator',
139
message: 'This field must be longer than 5 characters'
140
});
141
}
142
}
143
```
144
145
### FormlyFormBuilder
146
147
Injectable service for building and managing form structures from field configurations.
148
149
```typescript { .api }
150
/**
151
* Service for building forms from field configurations
152
*/
153
@Injectable({ providedIn: 'root' })
154
export class FormlyFormBuilder {
155
/**
156
* Build form controls and structure from field configurations
157
* @param form - The Angular FormGroup or UntypedFormGroup to build into
158
* @param fields - Array of field configurations
159
* @param model - The data model to bind to
160
* @param options - Form options and lifecycle hooks
161
*/
162
/**
163
* Build and configure form controls for field configurations
164
* @param field - Field configuration to build
165
* @returns Processed field configuration
166
*/
167
build(field: FormlyFieldConfigCache): FormlyFieldConfigCache;
168
}
169
```
170
171
**Usage Example:**
172
173
```typescript
174
import { Component, OnInit } from '@angular/core';
175
import { FormGroup } from '@angular/forms';
176
import { FormlyFormBuilder, FormlyFieldConfig, FormlyFormOptions } from '@ngx-formly/core';
177
178
@Component({
179
selector: 'app-dynamic-form',
180
template: `
181
<form [formGroup]="form">
182
<formly-form [form]="form" [fields]="fields" [model]="model" [options]="options">
183
</formly-form>
184
</form>
185
`
186
})
187
export class DynamicFormComponent implements OnInit {
188
form = new FormGroup({});
189
model = {};
190
fields: FormlyFieldConfig[] = [];
191
options: FormlyFormOptions = {};
192
193
constructor(private formBuilder: FormlyFormBuilder) {}
194
195
ngOnInit() {
196
this.fields = [
197
{
198
key: 'firstName',
199
type: 'input',
200
props: { label: 'First Name', required: true }
201
},
202
{
203
key: 'lastName',
204
type: 'input',
205
props: { label: 'Last Name', required: true }
206
}
207
];
208
209
// Manually build the form (usually done automatically by FormlyForm component)
210
this.formBuilder.buildForm(this.form, this.fields, this.model, this.options);
211
}
212
}
213
```
214
215
## Types
216
217
### Service Configuration Types
218
219
```typescript { .api }
220
interface FormlyConfigExtras {
221
/** Whether to check expressions on form initialization */
222
checkExpressionOn?: 'modelChange' | 'changeDetectionCheck';
223
224
/** Whether to immediately render extensions */
225
immutable?: boolean;
226
227
/** Whether to show errors immediately */
228
showError?: (field: FormlyFieldConfig) => boolean;
229
230
/** Custom error state matcher */
231
errorStateMatcher?: ErrorStateMatcher;
232
233
/** Field transform function */
234
fieldTransform?: (
235
fields: FormlyFieldConfig[],
236
model: any,
237
form: FormGroup | UntypedFormGroup,
238
options: FormlyFormOptions
239
) => FormlyFieldConfig[];
240
241
/** Whether to reset field values when hidden */
242
resetFieldOnHide?: boolean;
243
244
/** Whether to render fields when hidden */
245
renderFormlyFieldElement?: boolean;
246
247
/** Whether to remove form control when field is hidden */
248
removeFormControlOnHide?: boolean;
249
250
/** Class name to add to formly-field elements */
251
formlyFieldElementClassName?: string;
252
253
/** Whether to use legacy API */
254
useLegacyAPI?: boolean;
255
}
256
257
interface ErrorStateMatcher {
258
/**
259
* Determine if field should show error state
260
* @param control - The form control
261
* @param form - The parent form
262
* @returns True if error should be shown
263
*/
264
isErrorState(control: AbstractControl | null, form: FormGroupDirective | NgForm | null): boolean;
265
}
266
```
267
268
### Service-Related Interfaces
269
270
```typescript { .api }
271
interface FormlyFormOptions {
272
/** Shared state object accessible to all fields */
273
formState?: any;
274
275
/** Subject for listening to field value changes */
276
fieldChanges?: Subject<FormlyValueChangeEvent>;
277
278
/** Function to transform fields before rendering */
279
fieldTransform?: (
280
fields: FormlyFieldConfig[],
281
model: any,
282
form: FormGroup | UntypedFormGroup,
283
options: FormlyFormOptions
284
) => FormlyFieldConfig[];
285
286
/** Custom function to determine when to show field errors */
287
showError?: (field: FormlyFieldConfig) => boolean;
288
289
/** Whether to reset field values when fields are hidden */
290
resetOnHide?: boolean;
291
292
/** Parent form directive for nested forms */
293
parentForm?: FormGroupDirective | null;
294
295
/** Function to update initial values */
296
updateInitialValue?: () => void;
297
298
/** Function to check field expressions */
299
checkExpressions?: (field: FormlyFieldConfig, ignoreCache?: boolean) => void;
300
301
/** Function to trigger change detection */
302
detectChanges?: (field: FormlyFieldConfig) => void;
303
304
/** Function to build field configurations */
305
build?: (field?: FormlyFieldConfig) => FormlyFieldConfig[];
306
307
// Internal properties
308
_resolver?: ComponentFactoryResolver;
309
_viewContainerRef?: ViewContainerRef;
310
_markForCheck?: (field: FormlyFieldConfig) => void;
311
_hiddenFieldsForCheck?: FormlyFieldConfig[];
312
_initialModel?: any;
313
}
314
315
interface FormlyValueChangeEvent {
316
/** The field that triggered the change */
317
field: FormlyFieldConfig;
318
319
/** The field type that changed */
320
type: string;
321
322
/** The new value */
323
value: any;
324
}
325
```