Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

For custom form components, is it possible to use DefaultValueAccessor instead of ControlValueAccessor?

Tags:

angular

I need to be able to use the formControlName directive for my custom component.

I've been reading through the multiple SO questions about implementing ControlValueAccessor for a child component, and it all seems very fragile.

A lot of the examples are transforming <div> or <span> elements into form elements, and so it makes sense to implement all the functionality expected by ControlValueAccessor.

However, my component is just using the native <input> element. I'm creating a separate component because I want to use some icons with the input, and I obviously don't want to copy/paste the icon css everywhere.

I've come across the DefaultValueAccessor class which seems to be what's used by angular for all the native input elements. Can I leverage this behavior somehow for my custom component as well?

I just don't want to replicate this functionality. It could be difficult to maintain it over the long term with regards to bugs and various browser behavior. I would rather just use the functionality that's already associated with the native inputs.

Edit

Here's the code snippet of <jg-search> (my custom component):

<div>
    <svg>
        <!-- some content -->
    </svg>
    <label for="search">Search</label>
    <input id="search" type="text"></input>
    <svg>
        <!-- some content -->
    </svg>
</div>

I want to be able to just call it this way in a form: <jg-search formControlName="keyword">.

This is possible by implementing ControlValueAccessor in the SearchComponent. But since I'm just using the native <input type="text">, I don't want to reimplement the functionality already defined in DefaultValueAccessor.

like image 424
gjvatsalya Avatar asked May 03 '18 16:05

gjvatsalya


People also ask

Why use ControlValueAccessor?

ControlValueAccessor provides the ability to use FormControl with any component that implements this interface. This gives a lot of development flexibility and is a useful feature in Angular Forms . There are several ways with some boilerplate to control decoration and usage.

When registerOnChange called?

The registerOnChange method should be called whenever the value changes - in our case, when a star is clicked on. The registerOnTouched method should be called whenever our UI is interacted with - like a blur event.

What is a value Accessor?

Control Value Accessor is an interface that provides us the power to leverage the Angular forms API and create a communication between Angular Form API and the DOM element. It provides us many facilities in angular like we can create custom controls or custom component with the help of control value accessor interface.


Video Answer


1 Answers

One possible solution could be using ngDefaultControl attribute on your custom component:

<div [formGroup]="form">
    <jg-search formControlName="x" ngDefaultControl></jg-search>
                                   ^^^^^^^^^^^^^^^^
</div>

now all you need to do is to link your input element with existing FormControl as follows:

@Component({
  selector: 'jg-search',
  template: `
   <input [formControl]="ngControl.control">
  `
})
export class MyInput {
  constructor(public ngControl: NgControl) {}
}

For more detals see Ng-run Example

like image 99
yurzui Avatar answered Nov 15 '22 06:11

yurzui