Skip to content

Commit d9d8c77

Browse files
authored
feat: add support native Angular validators (#183), support correct work with isOptional (#188), add excludeGroups for fix recursive errors and unexpected creation of submodels (#185)
Add support native Angular validators #183 ``` this.form = this.fb.rootFormGroup( ComboCompany, { name: undefined, // issue #188 regionNum: undefined, // issue #188 }, { angularValidators: { regionNum: [Validators.required] } } // issue #183 ); ``` v2: "Greedy" creation of nested Models causes recursive errors and unexpected creation of submodels #185 ``` export class Company { ... @ValidateNested() @type(() => Department) @expose({ groups: ['nested'] }) department?: Department | undefined; ... } ... this.form = this.formBuilder.rootFormGroup( Department, this.getEmptyDepartment(), { classTransformOptions: { excludeGroups: ['nested'], }, } ); ... ```
1 parent c5bc6bc commit d9d8c77

22 files changed

+369
-121
lines changed

CHANGELOG.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ All notable changes to this project will be documented in this file. See [standa
44

55
### [2.0.1](https://github.com/EndyKaufman/ngx-dynamic-form-builder/compare/v2.0.0...v2.0.1) (2022-01-23)
66

7-
87
### Bug Fixes
98

10-
* update readme ([f7f9ca3](https://github.com/EndyKaufman/ngx-dynamic-form-builder/commit/f7f9ca3e3abf955a6c4425c679aaa5c216d4c5e8))
9+
- update readme ([f7f9ca3](https://github.com/EndyKaufman/ngx-dynamic-form-builder/commit/f7f9ca3e3abf955a6c4425c679aaa5c216d4c5e8))
1110

1211
## 2.0.0 (2022-01-23)
1312

apps/demo/src/app/panels/combo-company-panel/combo-company-panel.component.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
[placeholder]="strings.regionNum"
1818
/>
1919
<mat-error *ngIf="errors?.['regionNum']?.length">{{
20-
errors?.['regionNum'][0]
20+
errors?.['regionNum']
2121
}}</mat-error>
22-
<!--mat-error *ngIf="nativeErrors?.regionNum?.required">
22+
<mat-error *ngIf="form.get('regionNum')?.errors?.['required']">
2323
{{ 'region num should not be empty (native angular)' | transloco }}
24-
</mat-error-->
24+
</mat-error>
2525
</mat-form-field>
2626
<div class="full-width">
2727
<p>Form status: {{ form.status | json }}</p>

apps/demo/src/app/panels/combo-company-panel/combo-company-panel.component.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
2+
import { Validators } from '@angular/forms';
23
import { DynamicFormBuilder, DynamicFormGroup } from 'ngx-dynamic-form-builder';
34
import { ComboCompany } from './../../shared/models/combo-company';
45

@@ -26,14 +27,19 @@ export class ComboCompanyPanelComponent {
2627
savedItem?: ComboCompany;
2728

2829
constructor() {
29-
this.form = this.fb.rootFormGroup(ComboCompany, {
30-
name: '',
31-
regionNum: '',
32-
});
30+
this.form = this.fb.rootFormGroup(
31+
ComboCompany,
32+
{
33+
name: undefined,
34+
regionNum: undefined,
35+
},
36+
{ angularValidators: { regionNum: [Validators.required] } }
37+
);
3338
}
3439
onLoadClick(): void {
3540
this.savedItem = undefined;
3641
this.form.json = this.jsonItem;
42+
console.log(this.form);
3743
}
3844
onLoadAsObjectClick(): void {
3945
this.savedItem = undefined;
@@ -43,6 +49,7 @@ export class ComboCompanyPanelComponent {
4349
object.regionNum = this.jsonItem.regionNum;
4450
object.nameLocale = this.jsonItem.nameLocale;
4551
this.form.object = object;
52+
console.log(this.form);
4653
}
4754
onClearClick(): void {
4855
this.savedItem = undefined;
@@ -53,6 +60,7 @@ export class ComboCompanyPanelComponent {
5360
this.form.object = new ComboCompany();
5461
}
5562
onSaveClick(): void {
63+
console.log(this.form);
5664
if (this.form.valid) {
5765
this.savedItem = this.form.json;
5866
} else {

apps/demo/src/app/panels/i18n-company-panel/i18n-company-panel.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
</mat-form-field>
1414
<mat-form-field class="full-width">
1515
<input matInput formControlName="name" [placeholder]="strings.name" />
16-
<mat-error *ngIf="errors?.['name']?.messages?.length > 0">{{
16+
<mat-error *ngIf="errors?.['name']?.length > 0">{{
1717
errors?.['name'][0]
1818
}}</mat-error>
1919
</mat-form-field>

apps/demo/src/app/panels/new-api/new-api.component.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
ValidatorConstraintInterface,
1818
} from 'class-validator-multi-lang';
1919
import {
20+
DeepPartial,
2021
DynamicFormBuilder,
2122
DynamicFormGroup,
2223
getCustomDataToRootFormGroup,
@@ -106,6 +107,11 @@ export class Company {
106107
@IsBoolean({ each: true })
107108
@Expose()
108109
permissions!: boolean[];
110+
111+
@ValidateNested()
112+
@Type(() => Department)
113+
@Expose({ groups: ['nested'] })
114+
department?: Department | undefined;
109115
}
110116

111117
export class PeopleAge {
@@ -224,7 +230,12 @@ export class NewApiComponent {
224230
constructor() {
225231
this.form = this.formBuilder.rootFormGroup(
226232
Department,
227-
this.getEmptyDepartment()
233+
this.getEmptyDepartment(),
234+
{
235+
classTransformOptions: {
236+
excludeGroups: ['nested'],
237+
},
238+
}
228239
);
229240
console.log(this.form);
230241
}
@@ -250,7 +261,7 @@ export class NewApiComponent {
250261
}
251262

252263
onLoadClick(): void {
253-
this.form.json = this.getExampleDepartment();
264+
this.form.json = this.getExampleDepartment() as Department;
254265
console.log(this.form);
255266
}
256267

@@ -267,7 +278,7 @@ export class NewApiComponent {
267278
onClearClick(): void {
268279
this.savedItem$.next(undefined);
269280

270-
this.form.json = this.getEmptyDepartment();
281+
this.form.json = this.getEmptyDepartment() as Department;
271282
console.log(this.form);
272283
}
273284

@@ -281,7 +292,7 @@ export class NewApiComponent {
281292

282293
//
283294

284-
private getExampleDepartment(): Department {
295+
private getExampleDepartment(): DeepPartial<Department> {
285296
return {
286297
id: 11,
287298
name: 'dep name 1',
@@ -292,6 +303,7 @@ export class NewApiComponent {
292303
state: 'California',
293304
house: '221b',
294305
permissions: [true, false],
306+
department: { name: 'name' },
295307
},
296308
groups: [
297309
{ id: 33, name: 'group name 1' },
@@ -314,7 +326,7 @@ export class NewApiComponent {
314326
};
315327
}
316328

317-
private getEmptyDepartment(): Department {
329+
private getEmptyDepartment(): DeepPartial<Department> {
318330
return {
319331
name: '',
320332
company: {
@@ -327,7 +339,7 @@ export class NewApiComponent {
327339
cabinets: [],
328340
peopleAges: [],
329341
transports: [],
330-
} as unknown as Department;
342+
} as DeepPartial<Department>;
331343
}
332344

333345
// permissions

apps/demo/src/app/panels/project-panel/project-panel-step-2.component.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ <h4>
2727
<mat-error *ngIf="errors?.['tasks']?.length">{{
2828
errors?.['tasks']?.join(', ')
2929
}}</mat-error>
30-
<!--mat-error *ngIf="nativeErrors?.maxLength3">{{
31-
'Tasks max length = 3 (native angular)' | transloco
32-
}}</mat-error-->
30+
<mat-error *ngIf="form.errors?.['maxLength3']">
31+
{{ 'Tasks max length = 3 (native angular)' | transloco }}
32+
</mat-error>
3333
</h4>
3434
<mat-list role="list">
3535
<mat-list-item

apps/demo/src/app/panels/project-panel/project-panel-step-2.component.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,12 @@ export class ProjectPanelStep2Component implements OnDestroy {
4646
classValidatorOptions: {
4747
groups: [ProjectPanelStepsEnum.Step2],
4848
},
49-
validator: this.classLevelValidator,
49+
validators: this.classLevelValidator,
5050
}
5151
);
5252
}
5353
classLevelValidator(group: DynamicFormGroup<Project>) {
54-
return group.object && group.object.tasks && group.object.tasks.length > 3
55-
? { maxLength3: true }
56-
: null;
54+
return group?.value?.tasks?.length > 3 ? { maxLength3: true } : null;
5755
}
5856
getTasksArray() {
5957
return this.form.get('tasks') as FormArray;

apps/demo/src/assets/i18n/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"Experimental: registration panel": "Experimental: registration panel",
55
"Other files": "Other files",
66
"New API": "New API",
7+
"region num should not be empty (native angular)": "region num should not be empty (native angular)",
78
"Login form": "Login form",
89
"Username": "Username",
910
"Password": "Password",
@@ -35,6 +36,7 @@
3536
"Save": "Save",
3637
"email": "email",
3738
"dateOfBirth": "dateOfBirth",
39+
"Tasks max length = 3 (native angular)": "Tasks max length = 3 (native angular)",
3840
"English": "English",
3941
"Russian": "Русский",
4042
"Experimental + transloco + i18n": "Experimental + transloco + i18n",
@@ -52,7 +54,6 @@
5254
"Only abc field": "Only abc field",
5355
"it should match the cool 'abc' string": "it should match the cool 'abc' string",
5456
"$constraint1 do not match to $property": "$constraint1 do not match to $property",
55-
"region num should not be empty (native angular)": "region num should not be empty (native angular)",
5657
"Form native errors:": "Form native errors:",
5758
"name": "name",
5859
"regionNum": "regionNum",

apps/demo/src/assets/i18n/ru.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"Experimental: registration panel": "Экспериментально: регистрационная панель",
55
"Other files": "Другие файлы",
66
"New API": "Новое АПИ",
7+
"region num should not be empty (native angular)": "номер региона не должен быть пустым (нативный angular)",
78
"Login form": "Форма входа",
89
"Username": "Имя пользователя",
910
"Password": "Пароль",
@@ -35,6 +36,7 @@
3536
"Save": "Сохранить",
3637
"email": "эл. адрес",
3738
"dateOfBirth": "дата рождения",
39+
"Tasks max length = 3 (native angular)": "Tasks max length = 3 (native angular)",
3840
"English": "English",
3941
"Russian": "Русский",
4042
"Experimental + transloco + i18n": "Экспериментально + transloco + перевод",
@@ -52,7 +54,6 @@
5254
"Only abc field": "Должно включать только abc",
5355
"it should match the cool 'abc' string": "он должен соответствовать классной строке 'abc'",
5456
"$constraint1 do not match to $property": "$constraint1 не равно $property",
55-
"region num should not be empty (native angular)": "номер региона не должен быть пустым (нативный angular)",
5657
"Form native errors:": "Нативные ошибки:",
5758
"name": "название",
5859
"regionNum": "номер региона",

cypress.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"viewportWidth": 1024,
3-
"viewportHeight": 1024,
3+
"viewportHeight": 1524,
44
"reporter": "cypress-multi-reporters",
55
"reporterOptions": {
66
"reporterEnabled": "mochawesome",

0 commit comments

Comments
 (0)