Results are only displayed upon submitting for the second time

Struggling with implementing a change password feature in Angular 7,

On the backend side, if the current password is incorrect, it will return true.

An error message should appear on the Angular side, but I'm encountering an issue where I have to click the submit button twice to show the error message. Even though I can see the response in logs printing true value, the *ngIf directive is not working as expected.

Template:

    <span *ngIf="hasError">
         Wrong current password value  
    </span>

Component:

hasError: boolean;

 submit () {
     this.apiService
    .changePassword(this.formGroup.value).subscribe(res => {
  console.log(res);
  this.hasError = res;    });

Service:

  changePassword(body: any){
     return this.http.post<any>(this.url + 'changePassword', body);
  }

Could someone provide insight into why I need to click the submit button twice to display the HTML element?

Thank you

Answer №1

It seems like you have set

changeDetection: ChangeDetectionStrategy.OnPush
in the component decorator. As a result, Angular will not detect changes until the next change detection cycle, which may only happen after the second click.

To resolve this issue, you can inject ChangeDetectorRef in the constructor and trigger the change detection manually. Here's an example:

  constructor(private cdr: ChangeDetectorRef) {}
  
  hasError: boolean;

  submit () {
     this.apiService
    .changePassword(this.formGroup.value)
    .subscribe(res => {
       console.log(res);
       this.hasError = res;    
       this.cdr.markForCheck();  // <<<---- detect changes
  });

Alternatively, you can also solve this problem by using observables and the Angular async pipe.

  hasError$: new Subject();

  submit () {
    this.apiService
    .changePassword(this.formGroup.value)
    .subscribe(res => this.hasError$.next(res));

In your template, you can use:

  <span *ngIf="hasError$ | async">
       wrong current password value  
  </span>

Answer №2

This is the root cause of the problem

hasError: boolean;

You have declared the variable but failed to assign a value at the beginning. Consequently, when the component loads, the value of hasError defaults to undefined/null. This leads to the template being rendered with that default value.

Solution:

Option 1) (less recommended)

// If you prefer not initializing the value in the component.ts file, make this modification in 
  the HTML file:

<span *ngIf="!!hasError">
         Display error message here
</span>

The use of '!!' checks for the null status of the variable.

Option 2) Recommended

// Initialize the variable to false,

// In the component.ts file

hasError: boolean = false; // CRUCIAL

By setting the initial value to false, your code can remain unchanged. When the service is subscribed, the value can be set to true or false without affecting the HTML structure.

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

problems encountered when testing azure containerclient.listblobsbyhierarchy using sinon

I have developed a REST endpoint with the code "/files/lookup", which is designed to receive a query parameter folderPath and return a list of files with details, excluding content but including metadata. The endpoint connects to Azure Blob Stora ...

What steps should I take to fix the Typescript error showing up in my Next.js route?

import type { NextApiRequest, NextApiResponse } from "next"; import db from "../../app/libs/dbConn"; interface DataProps { auth: [ { name?: string; email?: string; passwordHash?: string; } ]; status: n ...

Error in Angular-CLI and TypeORM: Module parsing failed due to the presence of 'import' and 'export' statements, which are only allowed with 'sourceType: module'

When attempting to integrate typeorm into a new angular-cli project, I encounter a compiler error as soon as I reference typeorm. ./node_modules/typeorm/browser/index.js:3:0 - Error: Module parse failed: 'import' and 'export' may appear ...

Angular: Converting JSON responses from HttpClient requests into class instances

I am facing an issue with the following code: public fetchResults(searchTerm: string): Observable<Array<SearchResult>> { let params = new HttpParams().set('searchTerm', searchTerm); return this.http .get<Array< ...

Can you explain how to specify individual keys in an object literal in TypeScript?

So I've been working with this data structure export interface StoreData { msdb: {[tableName: string]: List<StoreModel>}; } However, I'm looking to restrict and enable auto-completion for specific string values in my tableName field. ...

The default selected item in Material Select does not function properly on the second attempt

Is there a way to reset an Angular Material Select Component to its default value after manually changing it on the UI screen? It seems to work fine during initialization but not after manual changes. I am attempting to create a button that will revert th ...

The Vue store array declaration triggers a TS error stating that it is not assignable to a parameter of type never

I'm puzzled as to why this error keeps showing up: Argument of type '{ id: string; }' is not assignable to parameter of type 'never'. ... appearing at const index = state.sections.findIndex((section) => section.id === id); T ...

Having trouble with sending values to Angular 7 components' HTML pages

Struggling with a simple task and encountering an error: Code snippet below: app.component.html <div class="col-md-{{myvalue}}">stuff here</div> app.component.ts myvalue: string; ngOnInit() { this.myvalue('6'); } Seeing th ...

What is the best way to determine which option is most suitable: types, classes, or function types in TypeScript for

Currently, I am developing a small todo command line utility with a straightforward program structure. The main file is responsible for parsing the command line arguments and executing actions such as adding or deleting tasks based on the input provided. E ...

What is the significance of the IRenderFunction interface definition in FluentUI?

Recently diving into TypeScript, I've begun working with DetailsList in Fluent UI. Check it out here: https://developer.microsoft.com/en-us/fluentui#/controls/web/detailslist. I'm exploring the onRenderRow property, which is of type IRenderFunct ...

Implementing a click event to convert text to input in Angular 5

I'm struggling with setting values instead of just getting them. I want to switch from using divs to input fields and update the values when in "editMode". <div class="geim__sets"> <div *ngFor="let set of game.sets" class="geim__set"> ...

Whenever I attempt to launch my cross-platform application on an android device, an error occurs

I am currently in the process of developing a cross-platform application using NativeScript with Angular. While it runs smoothly on web, I encounter several errors when trying to run it on Android. Despite resolving many issues, there is one error that has ...

Developing a Customized Filtering Mechanism in Angular 8

I have some experience working in web development, but I am relatively new to Angular. My current project involves creating a simple filter for a table's column based on user input. However, I'm facing an issue where typing in a single letter fil ...

What is the best way to upgrade the "import {Http, Response} from @angular/http" module for Angular 6?

Here is a code snippet that I am working with: import { Injectable } from '@angular/core'; import { Dish } from '../shared/dish'; import { Observable } from 'rxjs'; import { HttpClient, HttpResponse } from '@angular/c ...

Specialized Character Formats in TypeScript

In my quest to enhance the clarity in distinguishing different types of strings within my program - such as absolute paths and relative paths, I am seeking a solution that ensures functions can only take or return specific types without errors. Consider t ...

What is the process for creating a new element and utilizing its reference to add child elements in React?

I've been struggling to create an HTML element in a parent component in React, and then access that component's div from a child component in order to add new elements to it. Despite multiple attempts, I can't seem to resolve the issue of p ...

The endpoint for sending a contact message at http://localhost:4200/contact/send is not found, resulting in

I have implemented a bootstrap form for email services in my angular 6 app with nodejs. I am using the nodemailer package to send emails from my app, however it is not working as expected. When I submit the form, I encounter the following error: zone.js:2 ...

When the frontend-maven-plugin executes the npm run build command, it encounters difficulty locating the package.json file

I am currently developing an application with a Spring Boot backend and an Angular frontend. To build the frontend, I am utilizing the frontend-maven-plugin in conjunction with Maven. However, when running "mvn spring-boot:run" command, an error is encount ...

Sharing API Results with All Components in Angular 7 using BehaviorSubject

My goal is to optimize an API call that fetches data about the current user (such as their username, full name, group memberships, email address, and more) by ensuring it's only made once per user session and that the data is shared across all compone ...

The latest version of IntelliJ Idea Ultimate, 2023.2.5, does not offer compatibility with the updated control flow features in Angular

I recently made the switch to Angular 17 in my project and noticed that Idea is not recognizing the new syntax in HTML templates. <mat-menu #menu="matMenu"> @for (menuItem of getData().menu.items; track menuItem) { & ...