Skip to content

Commit

Permalink
fix: Ivalidate formGroup if founded any castomValidationErrors
Browse files Browse the repository at this point in the history
  • Loading branch information
EndyKaufman committed Jan 21, 2019
1 parent ea47571 commit 26a26ec
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 19,44 @@ <h3>Create project: step-1</h3>
</mat-form-field>
<div class="full-width">
<p>Form status: {{ form.status | json }}</p>
<p *ngIf="!form.valid">
Form errors: {{errors | json}}
</p>
<p *ngIf="!form.valid">Form errors: {{errors | json}}</p>
</div>
<div class="full-width">
<button
mat-raised-button
(click)="onClearClick()">
Clear
</button>
<button
mat-raised-button
(click)="onNextStepClick()"
[disabled]="!form.valid"
cdkFocusInitial>
Next step
</button>
<div
class="full-width"
fxLayout.gt-md="row"
fxLayout.lt-md="column"
fxLayoutAlign="space-evenly stretch">
<div
fxFlex.gt-sm="50"
fxLayout="row"
fxLayoutAlign="start center">
<button
mat-raised-button
(click)="onClearClick()">
Clear
</button>
<button
mat-raised-button
(click)="onNextStepClick()"
[disabled]="!form.valid"
cdkFocusInitial>
Next step
</button>
</div>
<div
fxFlex.gt-sm="50"
fxLayout="row"
fxLayoutAlign="end center">
<button
mat-raised-button
(click)="onLoadExternalClick()">
Load external
</button>
<button
mat-raised-button
(click)="onClearExternalClick()">
Clear external
</button>
</div>
</div>
</form>
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 63,14 @@ export class ProjectPanelStep1Component implements OnDestroy {
this.form.validateAllFormFields();
}
}
onLoadExternalClick(): void {
this.form
.setExternalErrorsAsync({
name: ['external error']
})
.then(() => this.form.validateAllFormFields());
}
onClearExternalClick(): void {
this.form.clearExternalErrorsAsync().then(() => this.form.validateAllFormFields());
}
}
57 changes: 33 additions & 24 deletions libs/ngx-dynamic-form-builder/src/lib/utils/dynamic-form-group.ts
Original file line number Diff line number Diff line change
@@ -1,21 1,13 @@
import { AbstractControl, FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { classToClass, plainToClass } from 'class-transformer';
import { ClassType } from 'class-transformer/ClassTransformer';
import {
getFromContainer,
MetadataStorage,
validate,
validateSync,
ValidationError,
ValidationTypes,
Validator,
ValidatorOptions
} from 'class-validator';
import { getFromContainer, MetadataStorage, validate, validateSync, ValidationError, ValidationTypes, Validator, ValidatorOptions } from 'class-validator';
import { ValidationMetadata } from 'class-validator/metadata/ValidationMetadata';
import { cloneDeep, mergeWith } from 'lodash-es';
import 'reflect-metadata';
import { BehaviorSubject } from 'rxjs';
import { Dictionary, DynamicFormGroupField, ShortValidationErrors } from '../models';
import { foreverInvalid, FOREVER_INVALID_NAME } from '../validators/forever-invalid.validator';
import { DynamicFormControl } from './dynamic-form-control';

// Enforces the properties of the object, if supplied, to be of the original type or DynamicFormGroup or, FormArray
Expand Down Expand Up @@ -85,7 77,7 @@ export class DynamicFormGroup<TModel> extends FormGroup {
// Public API
validate(externalErrors?: ShortValidationErrors, validatorOptions?: ValidatorOptions) {
this.validateAsync(externalErrors, validatorOptions).then(
() => {},
() => { },
error => {
throw error;
}
Expand Down Expand Up @@ -114,6 106,23 @@ export class DynamicFormGroup<TModel> extends FormGroup {

this.formErrors = allErrors;
this.customValidateErrors.next(this.formErrors);

// todo: refactor, invalidate form if exists any allErrors
let usedForeverInvalid = false;
if (Object.keys(allErrors).filter(key => key !== FOREVER_INVALID_NAME).length === 0 && this.get(FOREVER_INVALID_NAME)) {
this.removeControl(FOREVER_INVALID_NAME);
usedForeverInvalid = true;
}
if (this.valid && Object.keys(allErrors).length > 0 && !this.get(FOREVER_INVALID_NAME)) {
this.addControl(FOREVER_INVALID_NAME, new FormControl('', [foreverInvalid]));
usedForeverInvalid = true;
}
if (usedForeverInvalid) {
this.updateValueAndValidity({
onlySelf: true,
emitEvent: false
});
}
} catch (error) {
throw error;
}
Expand Down Expand Up @@ -166,7 175,7 @@ export class DynamicFormGroup<TModel> extends FormGroup {

setExternalErrors(externalErrors: ShortValidationErrors) {
this.setExternalErrorsAsync(externalErrors).then(
() => {},
() => { },
error => {
throw error;
}
Expand Down Expand Up @@ -195,7 204,7 @@ export class DynamicFormGroup<TModel> extends FormGroup {

setValidatorOptions(validatorOptions: ValidatorOptions) {
this.setValidatorOptionsAsync(validatorOptions).then(
() => {},
() => { },
error => {
throw error;
}
Expand Down Expand Up @@ -330,7 339,7 @@ export class DynamicFormGroup<TModel> extends FormGroup {

if (object !== undefined) {
// Recursively get the value of all fields
Object.keys(this.controls).forEach(key => {
Object.keys(this.controls).filter(name => name !== FOREVER_INVALID_NAME).forEach(key => {
// Handle Group
if (this.controls[key] instanceof DynamicFormGroup) {
object[key] = (this.controls[key] as DynamicFormGroup<any>).object;
Expand Down Expand Up @@ -566,7 575,7 @@ export function getClassValidators<TModel>(
//

function createNestedValidate(objectToValidate: any, validationMetadata: ValidationMetadata) {
return function(control: FormControl) {
return function (control: FormControl) {
const isValid =
getValidateErrors(control, objectToValidate !== undefined ? objectToValidate : control.value, validatorOptions)
.length === 0;
Expand All @@ -579,7 588,7 @@ export function getClassValidators<TModel>(
conditionalValidations: ValidationMetadata[],
fieldName: string
) {
return function(control: FormControl) {
return function (control: FormControl) {
if (!control) {
return null;
}
Expand All @@ -599,7 608,7 @@ export function getClassValidators<TModel>(
}

function createCustomValidation(fieldName: string, validationMetadata: ValidationMetadata) {
return function(control: FormControl) {
return function (control: FormControl) {
const validateErrors: ValidationError[] = setObjectValueAndGetValidationErrors(
control,
fieldName,
Expand Down Expand Up @@ -694,8 703,8 @@ function setObjectValueAndGetValidationErrors(control: FormControl, key: string,
control.parent instanceof DynamicFormGroup
? (control.parent as DynamicFormGroup<any>).object
: control.parent
? control.parent.value
: {};
? control.parent.value
: {};

if (object) {
object[key] = control.value;
Expand All @@ -714,11 723,11 @@ function getIsValidResult(isValid: boolean, validationMetadata: ValidationMetada
return isValid
? null
: {
[errorType]: {
valid: false,
type: validationMetadata.type
}
};
[errorType]: {
valid: false,
type: validationMetadata.type
}
};
}

type ErrorPropertyName = 'nestedValidate' | 'customValidation' | 'dynamicValidate';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 1,10 @@
import { FormControl } from '@angular/forms';

export function foreverInvalid(c: FormControl) {
return {
foreverInvalid: {
valid: false
}
};
}
export const FOREVER_INVALID_NAME = 'foreverInvalid';

0 comments on commit 26a26ec

Please sign in to comment.