Angular Unit Test: Issue: Form control is missing a value accessor

I have structured my form field abstraction in a way that works in development but not in my unit test.

// required.control.ts
import { FormControl, Validators } from '@angular/forms';
    
    export class RequiredControl extends FormControl {
      protected textErrors: { [key: string]: string } = {
        required: 'Mandatory field'
      };
    
      constructor(value: string | any = '') {
        super(value);
    
        this.setValidators([Validators.required]);
      }
    
      get textError() {
        let message = '';
        for (const error in this.textErrors) {
          if (error && this.hasError(error) && this.dirty) {
            message = this.textErrors[error];
    
            return message;
          }
        }
    
        return message;
      }
    
      get state() {
        return this.valid || !this.dirty ? '' : 'error';
      }
    }

To streamline my form and separate the validation logic for each field, I import this file into my main component:

// my-component.component.ts
import { RequiredControl } from './required.control.ts';

@Component({})
export class MyComponent implements OnInit { // I skiped import for this OnInit

   reasonControl = new RequiredControl(null);

   constructor() {}

   ngOnInit() {
     this.requestForm = this.formBuilder.group({
      reason: this.reasonControl, // first method tried :(
      reason:this.reasonControl as FormControl, // second method tried :(
     });
   }
}

During my unit tests, I include the following setup:

beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [MyComponent],
      imports: [ReactiveFormsModule, FormsModule, RouterTestingModule] 
    })
}));

The template includes:

https://i.sstatic.net/NDBeM.png

Running the test results in the following error:

https://i.sstatic.net/hGIF2.png

Answer №1

After some troubleshooting, I discovered the solution to my problem was using the ngDefaultControl attribute in the input field. Here is how it's done:

https://i.sstatic.net/3E1HK.png

By adding this attribute, the test gained the necessary information to recognize the element as a FormControl in third-party components, which resolved the issue in my specific scenario.

Answer №2

It's not recommended to use ngDefaultControl in cases where the child component already implements the ControlValueAccessor interface manually.

A more optimal approach would be to extend from the DefaultValueAccessor class and implement the NG_VALUE_ACCESSOR provider.

For an alternative solution, you can refer to my response in this different SO thread:

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Refresh the information being received without initiating a new process

I am fetching data from an ngrx/store I have subscribed to the data this.store.select(somedataList) .subscribe(myList => { myList.propertyA = "a different value"; }); After modifying the property values upon subscription, I must update the data ...

Looking to convert a number into a star rating using Angular 5?

Currently, I am using Angular 5 and I am looking for a way to display my rating number as a star rating. I have come across several tutorials on star ratings, but they only seem to work when a user gives a rating. What I need is to simply show my number as ...

Deriving types from object combinations

Can the Foo type be 'flattened' to return { A?: string; B? number } in the code snippet below? type Foo = { A: string } | { B: number } type Flatten< T, Keys extends keyof T = T extends any ? keyof T : never, > = { [K in Keys]?: T[K] } ...

The mat-pagination component's mat-select feature is displaying unusual behavior

In a recent project I have created, users need to perform CRUD operations and view the output in a table. Everything is functioning properly, however, there are instances where the "mat-select" within the "mat-paginator" starts behaving strangely. This iss ...

Exploring the power of nesting views using *ngFor in Ionic framework

I am looking to design a screen that features nested views using the *ngFor loop. The data I have is in a two-dimensional array format and I want to iterate through it to display the same view for each row within each section. It should look something like ...

A software piece producing a JSX element that generates a single function

Is it possible to create a JSX element or component that returns a single function as its child? For instance: interface ComponentChildrenProps { someProp: string; } const Component: React.FC<ComponentProps> = ({ children }): JSX.Element => { ...

What is the best way to eliminate the # symbol in angular 5 URLs?

Currently, I am working on a project in Angular 5 and I need to remove the hash symbol (#) from my URL. The current URL looks like this: http://localhost:4200/#/product/add. While it works fine after being published on my domain, I encounter a 404 error ...

Tips for troubleshooting errors such as "Maximum call stack size exceeded"

I've been working on an Ionic/angular project that I paused for a while. When I resumed working on it, I encountered an error in the console. The unusual effect is that nothing is displayed for 10-15 seconds, then my app loads, but I don't notice ...

Problem with rendering React Router v4 ConnectedRouter on nested routes

The routes for the first level are correctly displayed from Layout.tsx, but when clicked on ResourcesUI.tsx, the content is not rendered as expected (see code below). The ResourceUI component consists of 2 sections. The left section contains links, and th ...

Develop a reusable input component in Angular

I have developed a custom text component with validation capabilities export class CustomInputComponent implements OnInit{ @Input() formGroup: FormGroup; @Input() label: string; @Input() placeholder: string; @Input() name: string; @Input() errorM ...

Error: The attribute 'detect' is not a valid property of object 'GraphModel'

I am currently experimenting with using TensorFlow JS to develop a real-time object detection application in Angular 13. My goal is to utilize a video element that captures footage from the webcam, and I am attempting to invoke the model.detect(video) meth ...

Two-way data binding in Angular 2 is a powerful feature that allows for

My goal is to construct a parent component called Action, which includes two child components named Infos and Localisation. I want to connect the inputs of the children with the parent model. This is the model: export class Action{ title: string; ...

Tips for resolving the issue of "The types 'GameState' and 'string' do not intersect, so this condition will always yield 'false'."

I need to display different components based on the value of gameStatus: import React from "react"; import { useAppSelector } from "./hooks/redux"; import EndScreen from "./pages/EndScreen"; import QuestionsPage from "./p ...

Managing errors in ErrorHandler and addressing them in HttpInterceptor

Can you explain the difference between error handling methods in Angular 7? Is it necessary to handle global errors in HttpInterceptor and also in Angular's built-in ErrorHandler? In the HttpInterceptor, what types of errors can be handled, and in the ...

Issues with hydrating React local storage hook in custom implementation within NextJS

Currently facing an issue while implementing the localstorage hook in NextJS. The error message I am encountering is: Error: Hydration failed because the initial UI does not match what was rendered on the server.. Any suggestions on what might be causing ...

Arranging elements within an outer array by the contents of their inner arrays

I need help organizing an array based on the alphabetical order of a specific value within the inner arrays. For example: I want to sort this array by the prefix "old," so old A, old B, etc. const array = [ { personName: "Vans", personTags: ["young", " ...

A function's behavior will vary depending on whether it is a property of an object or not

I've been observing some peculiar behavior: In a typical scenario, TypeScript usually raises an error when an object contains too many keys, like this: type Foo = { a: string; } const a: Foo = { a: "hello", b: "foo" // Ob ...

The i18next module encounters compilation issues when used in a React application with Typescript

In my React-Typescript project, I recently set up i18next for multi-language support. Despite following the official documentation guidelines, I encountered compilation errors when running the app: Property 'changeLanguage' does not exist on type ...

Converting multiple tiff image files into a single image in Angular 9: A step-by-step guide

I am currently developing a web application using Angular 9. I am looking to incorporate a feature that will enable the conversion of multiple Tiff images into a single PDF or window.URL.createObjectURL(blob) of pdf. let images = ["http://netghost.nar ...

Troubleshooting ngFor in Angular 5

I'm currently working on a component that needs to display data fetched from the server. export class CommerceComponent implements OnInit { dealList; ngOnInit() { this.getDeals(); } getDeals(){ this.gatewayService.se ...