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
This commit is contained in:
rellis-of-rhindleton
2018-02-09 17:19:26 -05:00
committed by mmalerba
parent cf54802e44
commit 98daab3935
+29 -9
View File
@@ -157,23 +157,43 @@ private _placeholder: string;
#### `ngControl`
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. In any real component, you would probably want to implement
`ControlValueAccessor` so that your component can work with `formControl` and `ngModel`.
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.
```ts
ngControl = null;
ngControl: NgControl = null;
```
If you did implement `ControlValueAccessor`, you could simply inject the `NgControl` and make it
publicly available. (For additional information about `ControlValueAccessor` see the
[API docs](https://angular.io/api/forms/ControlValueAccessor).)
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.
The easy way is to add it as a public property to your constructor and let dependency injection handle it:
```ts
constructor(..., @Optional() @Self() public ngControl: NgControl) { ... }
constructor(
...,
@Optional() @Self() public ngControl: NgControl,
...,
) { }
```
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.
To resolve this, remove the `NG_VALUE_ACCESSOR` provider and instead set the value accessor directly:
```ts
constructor(
...,
@Optional() @Self() public ngControl: NgControl,
...,
) {
// Setting the value accessor directly (instead of using
// the providers) to avoid running into a circular import.
if (this.ngControl != null) { this.ngControl.valueAccessor = this; }
}
```
For additional information about `ControlValueAccessor` see the [API docs](https://angular.io/api/forms/ControlValueAccessor).
#### `focused`
This property indicates whether or not the form field control should be considered to be in a