Skip to content

docs: expand example that removes value accessor provider #13860

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 36 additions & 11 deletions guides/creating-a-custom-form-field-control.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,20 @@ 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.
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: NgControl = null;
```

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.
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:
The easy way is to add it as a public property to your constructor and let dependency injection
handle it:

```ts
constructor(
Expand All @@ -177,19 +182,39 @@ constructor(
) { }
```

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.
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,
@Component({
...,
) {
// 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; }
providers: [
...,
// Remove this.
// {
// provide: NG_VALUE_ACCESSOR,
// useExisting: forwardRef(() => MatFormFieldControl),
// multi: true,
// },
],
})
class MyTelInput implements MatFormFieldControl<MyTel> {
constructor(
...,
@Optional() @Self() public ngControl: NgControl,
...,
) {

// Replace the provider from above with this.
if (this.ngControl != null) {
// Setting the value accessor directly (instead of using
// the providers) to avoid running into a circular import.
this.ngControl.valueAccessor = this;
}
}
}
```

Expand Down