Skip to content

Commit d0bcf79

Browse files
author
Sam Severance
committed
fix(examples): fix form-field-custom-control
* Update `MyTelInput` to implement `ControlValueAccessor` interface * Resolves #14810
1 parent 57aadc2 commit d0bcf79

File tree

2 files changed

+58
-8
lines changed

2 files changed

+58
-8
lines changed
Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
11
<div [formGroup]="parts" class="example-tel-input-container">
2-
<input class="example-tel-input-element" formControlName="area" size="3">
2+
<input class="example-tel-input-element"
3+
formControlName="area"
4+
size="3"
5+
(input)="_handleInput()"
6+
(blur)="_handleBlur($event)">
37
<span class="example-tel-input-spacer">&ndash;</span>
4-
<input class="example-tel-input-element" formControlName="exchange" size="3">
8+
<input class="example-tel-input-element"
9+
formControlName="exchange"
10+
size="3"
11+
(input)="_handleInput()"
12+
(blur)="_handleBlur($event)">
513
<span class="example-tel-input-spacer">&ndash;</span>
6-
<input class="example-tel-input-element" formControlName="subscriber" size="4">
14+
<input class="example-tel-input-element"
15+
formControlName="subscriber"
16+
size="4"
17+
(input)="_handleInput()"
18+
(blur)="_handleBlur($event)">
719
</div>

src/material-examples/form-field-custom-control/form-field-custom-control-example.ts

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {FocusMonitor} from '@angular/cdk/a11y';
22
import {coerceBooleanProperty} from '@angular/cdk/coercion';
3-
import {Component, ElementRef, Input, OnDestroy} from '@angular/core';
4-
import {FormBuilder, FormGroup} from '@angular/forms';
3+
import {Component, ElementRef, Input, OnDestroy, Optional, Self} from '@angular/core';
4+
import {FormBuilder, FormGroup, ControlValueAccessor, NgControl} from '@angular/forms';
55
import {MatFormFieldControl} from '@angular/material';
66
import {Subject} from 'rxjs';
77

@@ -30,17 +30,18 @@ export class MyTel {
3030
'[attr.aria-describedby]': 'describedBy',
3131
}
3232
})
33-
export class MyTelInput implements MatFormFieldControl<MyTel>, OnDestroy {
33+
export class MyTelInput implements ControlValueAccessor, MatFormFieldControl<MyTel>, OnDestroy {
3434
static nextId = 0;
3535

3636
parts: FormGroup;
3737
stateChanges = new Subject<void>();
3838
focused = false;
39-
ngControl = null;
4039
errorState = false;
4140
controlType = 'example-tel-input';
4241
id = `example-tel-input-${MyTelInput.nextId++}`;
4342
describedBy = '';
43+
onChange = (_: any) => {};
44+
onTouched = () => {};
4445

4546
get empty() {
4647
const {value: {area, exchange, subscriber}} = this.parts;
@@ -89,7 +90,12 @@ export class MyTelInput implements MatFormFieldControl<MyTel>, OnDestroy {
8990
this.stateChanges.next();
9091
}
9192

92-
constructor(fb: FormBuilder, private fm: FocusMonitor, private elRef: ElementRef<HTMLElement>) {
93+
constructor(
94+
fb: FormBuilder,
95+
private fm: FocusMonitor,
96+
private elRef: ElementRef<HTMLElement>,
97+
@Optional() @Self() public ngControl: NgControl) {
98+
9399
this.parts = fb.group({
94100
area: '',
95101
exchange: '',
@@ -100,6 +106,10 @@ export class MyTelInput implements MatFormFieldControl<MyTel>, OnDestroy {
100106
this.focused = !!origin;
101107
this.stateChanges.next();
102108
});
109+
110+
if (this.ngControl != null) {
111+
this.ngControl.valueAccessor = this;
112+
}
103113
}
104114

105115
ngOnDestroy() {
@@ -116,4 +126,32 @@ export class MyTelInput implements MatFormFieldControl<MyTel>, OnDestroy {
116126
this.elRef.nativeElement.querySelector('input')!.focus();
117127
}
118128
}
129+
130+
writeValue(tel: MyTel | null): void {
131+
this.value = tel;
132+
}
133+
134+
registerOnChange(fn: any): void {
135+
this.onChange = fn;
136+
}
137+
138+
registerOnTouched(fn: any): void {
139+
this.onTouched = fn;
140+
}
141+
142+
setDisabledState(isDisabled: boolean): void {
143+
this.disabled = isDisabled;
144+
}
145+
146+
_handleInput(): void {
147+
this.onChange(this.parts.value);
148+
}
149+
150+
_handleBlur(event: FocusEvent): void {
151+
const inputs = Array.from(this.elRef.nativeElement.querySelectorAll('input'));
152+
153+
if (!inputs.some(input => event.relatedTarget === input)) {
154+
this.onTouched();
155+
}
156+
}
119157
}

0 commit comments

Comments
 (0)