Skip to content

Commit

Permalink
have the children form components inputs trigger the touch onthe Cont…
Browse files Browse the repository at this point in the history
…rolValueAccessor
  • Loading branch information
gparlakov committed Mar 8, 2020
1 parent 0f18610 commit 26684cc
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 16 deletions.
8 changes: 4 additions & 4 deletions src/app/event-form/event-form.component.html
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
<div [formGroup]="form">
<mat-form-field>
<mat-label>Event name</mat-label>
<input type="text" matInput formControlName="eventName" required />
<input type="text" matInput formControlName="eventName" required (blur)="onNameInputBlur()" />
<mat-error>Event name is required</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Event location</mat-label>
<input type="text" matInput formControlName="location" />
<input type="text" matInput formControlName="location" (blur)="onLocationInputBlur()" />
</mat-form-field>
<mat-form-field>
<mat-label>Event start date</mat-label>
<input matInput formControlName="dateStart" required [matDatepicker]="dateStartPicker" />
<input matInput formControlName="dateStart" required [matDatepicker]="dateStartPicker" (blur)="onStartDateInputBlur()" />
<mat-datepicker-toggle matSuffix [for]="dateStartPicker"></mat-datepicker-toggle>
<mat-datepicker #dateStartPicker></mat-datepicker>
<mat-error>Please provide start date</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Event start time</mat-label>
<input matInput type="time" formControlName="timeStart" />
<input matInput type="time" formControlName="timeStart" (blur)="onStartTimeInputBlur()" />
</mat-form-field>
</div>
12 changes: 12 additions & 0 deletions src/app/event-form/event-form.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,16 @@ export class EventFormComponent
ngOnInit(): void {
super.ngOnInit();
}
onNameInputBlur() {
this.onTouch();
}
onLocationInputBlur() {
this.onTouch();
}
onStartDateInputBlur() {
this.onTouch();
}
onStartTimeInputBlur() {
this.onTouch();
}
}
1 change: 1 addition & 0 deletions src/app/party-form/party-form.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<button mat-raised-button color="primary" type="submit">
Submit <mat-spinner *ngIf="submitting" color="warn" diameter="15" style="display:inline-block"></mat-spinner>
</button>
<button type="reset" color="warn" mat-raised-button>Reset</button>
</form>

<fty-show-form-control [control]="form" name="Party Form" [closed]="true"></fty-show-form-control>
4 changes: 2 additions & 2 deletions src/app/person-contact/person-contact.component.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<div [formGroup]="form">
<mat-form-field>
<mat-label>Name</mat-label>
<input matInput formControlName="name"/>
<input matInput formControlName="name" (blur)="onNameInputBlur()"/>
</mat-form-field>
<mat-form-field>
<mat-label>Email</mat-label>
<input matInput formControlName="email" required/>
<input matInput formControlName="email" required (blur)="onEmailInputBlur()"/>
<mat-error>Please provide person's email</mat-error>
</mat-form-field>
</div>
8 changes: 7 additions & 1 deletion src/app/person-contact/person-contact.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { ControlValueAccessorConnector } from '../shared/control-value-accessor-
styleUrls: ['./person-contact.component.css']
})
export class PersonContactComponent extends ControlValueAccessorConnector<PersonContact> implements OnInit {

constructor(@Self() @Optional() controlDirective: NgControl) {
super(
controlDirective,
Expand All @@ -24,4 +23,11 @@ export class PersonContactComponent extends ControlValueAccessorConnector<Person
ngOnInit(): void {
super.ngOnInit();
}

onNameInputBlur() {
this.onTouch();
}
onEmailInputBlur() {
this.onTouch();
}
}
16 changes: 9 additions & 7 deletions src/app/shared/control-value-accessor-connector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Subscription } from 'rxjs';
export class ControlValueAccessorConnector<T, C extends Controls<T> = Controls<T>>
implements OnInit, OnDestroy, ControlValueAccessor {
protected subs = new Subscription();
protected callingOnTouchFromBelow: boolean;
protected touchIsChildInitiated: boolean;

public form: TypedFormGroup<T, C>;

Expand All @@ -20,16 +20,14 @@ export class ControlValueAccessorConnector<T, C extends Controls<T> = Controls<T
ngOnInit(): void {
if (this.directive && this.directive.control) {
forEachControlIn(this.form)
.markAsTouchedSimultaneouslyWith(this.directive.control, () => this.callingOnTouchFromBelow)
.markAsTouchedSimultaneouslyWith(this.directive.control, () => this.touchIsChildInitiated)
.addValidatorsTo(this.directive.control);
}

const values = this.form.valueChanges.subscribe(v => this.onChange(v));
const statuses = this.form.statusChanges.subscribe(s => {
if (this.form.touched) {
this.callingOnTouchFromBelow = true;
this.onTouch();
this.callingOnTouchFromBelow = false;
}
});

Expand All @@ -40,16 +38,20 @@ export class ControlValueAccessorConnector<T, C extends Controls<T> = Controls<T
ngOnDestroy(): void {
this.subs.unsubscribe();
}
private onChange = (_: T) => {};
private onTouch = () => {};
protected onChange = (_: T) => {};
protected onTouch = () => {};
writeValue(obj: any): void {
this.form.patchValue(obj || {});
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouch = fn;
this.onTouch = () => {
this.touchIsChildInitiated = true;
fn();
this.touchIsChildInitiated = false;
};
}
setDisabledState(disable: boolean) {
disable ? this.form.disable() : this.form.enable();
Expand Down
4 changes: 2 additions & 2 deletions src/app/shared/forms-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ export function forEachControlIn(form: FormGroup | FormArray | TypedFormGroup<an
}
return composer;
},
markAsTouchedSimultaneouslyWith(c: AbstractControl, comingFromBelow?: () => boolean) {
markAsTouchedSimultaneouslyWith(c: AbstractControl, touchIsChildInitiated?: () => boolean) {
if (c != null) {
const markAsTouchedOriginal = c.markAsTouched.bind(c);
c.markAsTouched = () => {
markAsTouchedOriginal();
if (!comingFromBelow || !comingFromBelow()) {
if (!touchIsChildInitiated || !touchIsChildInitiated()) {
composer.call('markAsTouched');
}
};
Expand Down

1 comment on commit 26684cc

@gparlakov
Copy link
Owner Author

@gparlakov gparlakov commented on 26684cc Mar 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

closes #3

Please sign in to comment.