Skip to content

Commit f895622

Browse files
crisbetovivian-hu-zz
authored andcommitted
docs: expand example that removes value accessor provider (#13860)
In the form field guide, we instruct people to remove the `NG_VALUE_ACCESSOR` provider and replace it with injecting the `NgControl`, however it's not very explicit and is easy to miss. These changes expand the example a bit in an effort to make it harder to miss. Fixes #8158.
1 parent ce500dc commit f895622

File tree

1 file changed

+36
-11
lines changed

1 file changed

+36
-11
lines changed

guides/creating-a-custom-form-field-control.md

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -159,15 +159,20 @@ private _placeholder: string;
159159

160160
#### `ngControl`
161161

162-
This property allows the form field control to specify the `@angular/forms` control that is bound to this component. Since we haven't set up our component to act as a `ControlValueAccessor`, we'll just set this to `null` in our component.
162+
This property allows the form field control to specify the `@angular/forms` control that is bound
163+
to this component. Since we haven't set up our component to act as a `ControlValueAccessor`, we'll
164+
just set this to `null` in our component.
163165

164166
```ts
165167
ngControl: NgControl = null;
166168
```
167169

168-
It is likely you will want to implement `ControlValueAccessor` so that your component can work with `formControl` and `ngModel`. If you do implement `ControlValueAccessor` you will need to get a reference to the `NgControl` associated with your control and make it publicly available.
170+
It is likely you will want to implement `ControlValueAccessor` so that your component can work with
171+
`formControl` and `ngModel`. If you do implement `ControlValueAccessor` you will need to get a
172+
reference to the `NgControl` associated with your control and make it publicly available.
169173

170-
The easy way is to add it as a public property to your constructor and let dependency injection handle it:
174+
The easy way is to add it as a public property to your constructor and let dependency injection
175+
handle it:
171176

172177
```ts
173178
constructor(
@@ -177,19 +182,39 @@ constructor(
177182
) { }
178183
```
179184

180-
Note that if your component implements `ControlValueAccessor`, it may already be set up to provide `NG_VALUE_ACCESSOR` (in the `providers` part of the component's decorator, or possibly in a module declaration). If so you may get a *cannot instantiate cyclic dependency* error.
185+
Note that if your component implements `ControlValueAccessor`, it may already be set up to provide
186+
`NG_VALUE_ACCESSOR` (in the `providers` part of the component's decorator, or possibly in a module
187+
declaration). If so you may get a *cannot instantiate cyclic dependency* error.
181188

182189
To resolve this, remove the `NG_VALUE_ACCESSOR` provider and instead set the value accessor directly:
183190

184191
```ts
185-
constructor(
186-
...,
187-
@Optional() @Self() public ngControl: NgControl,
192+
@Component({
188193
...,
189-
) {
190-
// Setting the value accessor directly (instead of using
191-
// the providers) to avoid running into a circular import.
192-
if (this.ngControl != null) { this.ngControl.valueAccessor = this; }
194+
providers: [
195+
...,
196+
// Remove this.
197+
// {
198+
// provide: NG_VALUE_ACCESSOR,
199+
// useExisting: forwardRef(() => MatFormFieldControl),
200+
// multi: true,
201+
// },
202+
],
203+
})
204+
class MyTelInput implements MatFormFieldControl<MyTel> {
205+
constructor(
206+
...,
207+
@Optional() @Self() public ngControl: NgControl,
208+
...,
209+
) {
210+
211+
// Replace the provider from above with this.
212+
if (this.ngControl != null) {
213+
// Setting the value accessor directly (instead of using
214+
// the providers) to avoid running into a circular import.
215+
this.ngControl.valueAccessor = this;
216+
}
217+
}
193218
}
194219
```
195220

0 commit comments

Comments
 (0)