No Value Accessor For Form Control Name
Angular 15 Reactive Forms-Based Error
This error is so frustrating. Partially because this link is not adequate to help understand what is going on here with any depth, as it is entirely possible to create working forms in angular without any understanding of what a Value Accessor is in the first place.
So let’s go on a brief journey together to learn about this annoying (but useful) thing, and hopefully get past this error once and for good.
What is a value accessor?
From an OOP perspective
A value accessor is a means of accessing data from within a class. Private or not, if you have a property called “name”, a value accessor would be a method called something like “getName()” that would return that name property.
In Context
The value accessor we are talking about in this post is a JS object that acts as a bridge between the Angular forms API and a DOM element (hint hint). But what is its real role, and what is the directionality here? Is it both ways DOM <-> FormsAPI? Like, what does the value actually represent when I’m looking at the form?
More Specifically
A Value Accessor in Angular 15 is an instance of the class called ControlValueAccessor, and from what I can glean, is meant to serve as a way to access the values of DOM elements which inherently have a .value property.
In my case, I was attempting to bind the FormControl elements of a FormArray to a list of editable “chips”. I wanted the user to be able to edit the chips directly, and when I rolled this out, I kept getting this error, no matter which way I wanted to arrange it.
You will not see this error on DOM elements with a .value property
It seems Angular 15 has a built-in way of doing Value Accessing with the FormControls on DOM elements like an input field, a textarea, a radio button, etc. If it has a property .value, it just seems to work. I should dig into this more, but if I had to make a wild guess, it would be that the Angular Architecture expects the developer to do bindings to dom elements that have this property. So the class that interfaces with the dom element attempts to map 1:1 and throws if the mapping is not possible. Forcing the developer to compensate by either extending the class or adjusting the mapping in some kind of way.
I’m not getting into that for now.
Elements that do not have this property do not work without a custom implementation of ControlValueAccessor, or leveraging other angular tooling / decorators / services.
I didn’t find a good way around it using angular tools, but that doesn’t mean a way doesn’t exist. GitHub may have some good work-arounds.
I have verified that all these types of elements work in Angular 15:
<input>
<textarea>
<select>
<option>
<button>
Implementing your own ControlValueAccessor
I won’t give a how-to post on this when such a good one like this one already exists. I can definitely say I would only go through the trouble of this if it’s absolutely required. But I believe some clever structuring of components and input would allow for a dynamic wrapper component that could be used with virtually any child component and make it possible to write into a contentEditable component. I haven’t tried it but it seems possible.
Conclusion
The reason this error is occurring is probably that the DOM element is not supported out of the box by Angular to handle FormControls (Value Accessors Specifically). That or there could be an issue in the property, name, or hierarchy of the FormControlName assigned to that element.
It is possible to give elements that do not have built-in support to Value Accessors the capability of interfacing with the FormControl properly, but it requires building a wrapper component for that element in Angular with all the appropriate methods, and configuration.