Strange Bug in Angular Validation

Having an issue with my angular material stepper. The validation works fine, preventing advancement if nothing is selected. However, I'm seeing a console error that I can't decipher.

Below is the HTML code:

<mat-horizontal-stepper linear #stepper>
    <mat-step [stepControl]="frmUserDetails">
        <ng-template matStepLabel>Service User Details</ng-template>
        <form [formGroup]="frmUserDetails" name="frmUserDetails">
            <mat-form-field>
                <mat-select placeholder="Profile Type" formControlName="profileType" required>
                    <mat-option *ngFor="let type of baseAnswersMin" [value]="type">
                        {{ type }}
                    </mat-option>
                </mat-select>
            </mat-form-field>
        </form>
        <button mat-raised-button matStepperNext class="nav-btn pull-right">Next</button>
    </mat-step>

    <mat-step [stepControl]="step2.frmDrugUse">
        <ng-template matStepLabel>Drug Use</ng-template>
        <step-two-component #step2></step-two-component>
    </mat-step>

</mat-horizontal-stepper>

Here is the corresponding TypeScript code:

import { Component, ViewChild, Input } from '@angular/core';
import { FormGroup, Validators, FormBuilder } from '@angular/forms';
import { StepOneComponent } from './step-one/step-one.component';
import { StepTwoComponent } from './step-two/step-two.component';
import { StepThreeComponent } from './step-three/step-three.component';

@Component({
    selector: 'create-profile-component',
    templateUrl: './create-profile.component.html',
    styleUrls: ['./create-profile.component.css']
})

export class CreateProfileComponent {
    stepOne: any;
    frmUserDetails: FormGroup;


    baseAnswersMin = ['Yes', 'No', 'Declined to Answer'];

    constructor(private fb: FormBuilder) { 
        this.stepOne = {

        };
    }
    public ngOnInit() {
        this.frmUserDetails = this.fb.group({
            profileType: ['', Validators.required],
        });


    }    

}

Error message in the console:

ERROR TypeError: Cannot read property 'name' of undefined
    at checkBindingNoChanges (core.js:9912)
    at checkNoChangesNodeInline (core.js:13961)
    at checkNoChangesNode (core.js:13935)
    at debugCheckNoChangesNode (core.js:14764)
    at debugCheckDirectivesFn (core.js:14666)
    at Object.eval [as updateDirectives] (CreateProfileComponent.html:17)
    at Object.debugUpdateDirectives [as updateDirectives] (core.js:14648)
    at checkNoChangesView (core.js:13773)
    at callViewAction (core.js:14126)
    at execComponentViewsAction (core.js:14078)

The error seems to be originating from this part of the HTML:

<mat-option *ngFor="let type of baseAnswersMin" [value]="type">

And as requested, here is the code for the second step component:

TypeScript:

import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { CreateProfileComponent } from '../create-profile.component';
import { Observable } from 'rxjs/Rx';
import { ProfileService } from '../../../services/profile-service';
import { LookupInterface } from '../../../interfaces/lookup-interface';

@Component({
    selector: 'step-two-component',
    templateUrl: './step-two.component.html',
    styleUrls: ['../create-profile.component.css']
})
export class StepTwoComponent implements LookupInterface {
    lookups: any;
    frmDrugUse: FormGroup;
    stepTwo: any;

    constructor(private formBuilder: FormBuilder, private profileService: ProfileService) {
        this.stepTwo = {
            ageAtFirstUse: null
        };
    }

    ngOnInit() {
        this.frmDrugUse = this.formBuilder.group({
            ageAtFirstUse: ['', Validators.required]
        });

        this.setLookups();
    }

    setLookups() {
        this.lookups = new Object();
        this.profileService.getLookups(2).subscribe(data => {
            this.lookups = data;
        }, err => console.error(err))
    }

}

HTML:

<div>
    <mat-card-title>Drug Use</mat-card-title>
    <mat-card-subtitle>Complete the below fields regarding the service user's history with drugs</mat-card-subtitle>
</div>

<form [formGroup]="frmDrugUse" name="frmDrugUse">
    <mat-form-field>
        <input type="number" matInput placeholder="Age First Used Drugs">
    </mat-form-field>

    <mat-form-field>
        <mat-select placeholder="Current Injecting Status">
            <mat-option *ngFor="let status of lookups.injectingStatus" [value]="status.value">{{ status.value }}</mat-option>
        </mat-select>
    </mat-form-field>

    <!-- More form fields for drug use information -->

    <mat-card-actions>
        <button mat-raised-button matStepperNext class="nav-btn pull-right" style="margin-left:5px;">Next</button>
        <button mat-raised-button matStepperPrevious class="nav-btn pull-right">Previous</button>
    </mat-card-actions>

</form>

Answer №1

This issue arises from the following section of your code:

<mat-step [stepControl]="step2.frmDrugUse">
  <step-two-component #step2></step-two-component>

For a demonstration, you can view it in this live example

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

The error occurs because you are referring to a property that has not been initialized when Angular checks the stepControl binding.

To resolve this issue, consider using a Promise in the StepTwoComponent:

step-two.component.ts

ngOnInit() {
  Promise.resolve(null).then(() => {
    this.frmDrugUse = this.formBuilder.group({
      ageAtFirstUse: ['', Validators.required]
    });

    this.setLookups();
  })
}

step-two.component.html

<form *ngIf="frmDrugUse" [formGroup]="frmDrugUse" name="frmDrugUse">
      ^^^^^^^^^^^^^^^^^
     add also this

Here is an example

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

Ways to navigate to specific app information when tapping on the app

I am dealing with Json data models: Array<Model> = [ { name: 'kanban', version: '1', processes: [ { name: 'kanban', version: '1', descrption: 'k ...

The function "useLocation" can only be utilized within the scope of a <RouterProvider> in react-router. An Uncaught Error is thrown when trying to use useLocation() outside of a <Router>

When attempting to utilize the useLocation hook in my component, I encountered an error: import React, { useEffect } from 'react'; import { useLocation } from 'react-router-dom'; import { connect } from 'react-redux'; import { ...

Having trouble with setting up a Store with Ngrx in an Angular application

Could someone assist me in troubleshooting the error by analyzing the code provided below? I am new to Angular and unfamiliar with the Ngrx concept. You can also view a screenshot of the error here: https://i.sstatic.net/yhM0G.png package.json { "name": ...

What changes can be implemented to convert this function to an asynchronous one?

Is it possible to convert the following function into an asynchronous function? getHandledSheet(): void { this.timesheetService.getAllTimesheets().subscribe({next: (response: TimeSheet[]) => {this.timesheetsHandled = response.filter(sheet => ...

What is the best way to exclude an interface using a union type recursively in TypeScript?

I wish to recursively exclude types that are part of union types, and eliminate certain union types Here is an example. Normal and Admin should be considered as union types interface Admin { admin: never; } interface Normal { normal: never; } ...

Upon refreshing the page, the Vuex store getter displays [__ob__: Observer]

After each page refresh, my Vuex store getter returns [__ob__: Observer]. The version of Vue being used is 2.2.3 along with TypeScript. Initially, the data loads correctly from an external API, but when utilizing the getter, it fails and requires another ...

Cordova WebView proves to be less efficient compared to Android WebChromeClient in terms

After experimenting with Phonegap on my ASUS Zenfone 5 smartphone running Android 5.0, I noticed a significant lag in performance while using a web app built with AngularJS and Angular Material. The animations were slow, and even keyboard input was delayed ...

Expand the space between each pair of rows within a table

After implementing the code below: HTML <table> <tr> <th>Company</th> <th>Contact</th> <th>Country</th> </tr> <tr> <td>Alfreds Futterkiste</td ...

ESLint refuses to be turned off for a particular file

I am in the process of creating a Notes.ts file specifically for TypeScript notes. I require syntax highlighting but do not want to use eslint. How can I prevent eslint from running on my notes file? Directory Structure root/.eslintignore root/NestJS.ts r ...

Node.js has been giving me trouble as I try to install Inquirer

:***Hey Guys I'm Working on a TypeScript/JavaScript Calculator! ...

What is the best way to exclude multiple properties from an object in JavaScript?

Having two methods that return Pick<T, K> and Omit<T, K> types where Omit is defined as type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>, I am facing difficulty in removing multiple properties from an object. Th ...

How can I configure React Router V6 to include multiple :id parameters in a Route path, with some being optional?

Currently, I am utilizing react-router@6 and have a Route that was previously used in V5. The route is for vehicles and always requires one parameter (:id = vehicle id), but it also has an optional second parameter (:date = string in DD-MM-YYYY format): &l ...

Struggling to identify the memory leak in my Express.js Jest tests

Lately, I've been investing a considerable amount of time into identifying memory leaks within my Jest tests. While I have managed to resolve some issues, there is still a noticeable amount of memory leakage occurring from one test suite to the next. ...

Separate and handle multiple exceptions of the same instance individually

If I am facing the situation where multiple method calls to another class are possible, each of which could potentially throw the same exception that I am unable to modify, how can I handle each Exception separately without allowing the rest of the functio ...

Tips for efficiently managing angular route subscriptions and leveraging parameters for simultaneous http requests

I am seeking the best solution for the following situation: My goal is to trigger two parallel http requests when an Observable from the route parameters subscription fires. I attempted to use switchMap in combination with forkJoin, but unfortunately it ...

Inconsistencies in Angular/Express GET calls are leading to intermittent success and failure. The issue is accompanied by the error message: [ERR_HTTP_HEADERS_SENT]: Cannot set headers

The methodical process I follow for each GET call initiation involves several steps. Typically, the setup for all GET calls on my website is consistent and successful 99% of the time. However, there are some API calls that occasionally return a 404 error, ...

When attempting to use a value outside of its block, the function may return a

My current task involves querying one collection to retrieve IDs, then using those IDs to query another collection and send back the response. The process runs smoothly until I encounter an issue with retrieving values outside of a block when using forEach ...

Using ngFor to dynamically call functions

In my code, I have an array called 'actionsArray' which contains objects of type 'Action'. Each Action object has two parameters: the function name and a boolean value (which is currently not important). let actionsArray: Action[] = [{ ...

The Ag-Grid filter icon vanishes once data is retrieved

Currently using Ag Grid with Angular 2. Encountering an issue where the filter icon is not showing up in the grid header after fetching data and trying to apply a filter. https://i.sstatic.net/nfZJw.png The filter icon was visible until this specific li ...

How to check Internet upload speed in Angular without using a backend server?

I need help uploading a file to a folder within my Angular app's directory while it is running on localhost. I have been unable to find a solution that doesn't involve using backend technologies. For instance, I simply want to upload an image fi ...