Skip to content

Commit 6f6f92d

Browse files
rellis-of-rhindletonmmalerba
authored andcommitted
updated Creating a Custom Form Field doc ngControl section (#9855)
* Creating a custom form field docs -- updated ngControl section to reflect errors injecting NgControl If the component already implements ControlValueAccessor, injecting NgControl in the constructor (as described in the docs) may fail. Added an alternate way. * Update creating-a-custom-form-field-control.md * added word "provider" for clarity
1 parent b05ff10 commit 6f6f92d

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

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

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -157,23 +157,43 @@ private _placeholder: string;
157157

158158
#### `ngControl`
159159

160-
This property allows the form field control to specify the `@angular/forms` control that is bound to
161-
this component. Since we haven't set up our component to act as a `ControlValueAccessor`, we'll just
162-
set this to `null` in our component. In any real component, you would probably want to implement
163-
`ControlValueAccessor` so that your component can work with `formControl` and `ngModel`.
160+
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.
164161

165162
```ts
166-
ngControl = null;
163+
ngControl: NgControl = null;
167164
```
168165

169-
If you did implement `ControlValueAccessor`, you could simply inject the `NgControl` and make it
170-
publicly available. (For additional information about `ControlValueAccessor` see the
171-
[API docs](https://angular.io/api/forms/ControlValueAccessor).)
166+
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.
167+
168+
The easy way is to add it as a public property to your constructor and let dependency injection handle it:
172169

173170
```ts
174-
constructor(..., @Optional() @Self() public ngControl: NgControl) { ... }
171+
constructor(
172+
...,
173+
@Optional() @Self() public ngControl: NgControl,
174+
...,
175+
) { }
175176
```
176177

178+
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.
179+
180+
To resolve this, remove the `NG_VALUE_ACCESSOR` provider and instead set the value accessor directly:
181+
182+
```ts
183+
constructor(
184+
...,
185+
@Optional() @Self() public ngControl: NgControl,
186+
...,
187+
) {
188+
// Setting the value accessor directly (instead of using
189+
// the providers) to avoid running into a circular import.
190+
if (this.ngControl != null) { this.ngControl.valueAccessor = this; }
191+
}
192+
```
193+
194+
For additional information about `ControlValueAccessor` see the [API docs](https://angular.io/api/forms/ControlValueAccessor).
195+
196+
177197
#### `focused`
178198

179199
This property indicates whether or not the form field control should be considered to be in a

0 commit comments

Comments
 (0)