The Angular Button fails to display when all input conditions are met

I'm currently working on validating a form using this link. The requirement is simple - when an input field is invalid, the `save` button should be disabled. Conversely, when all input fields are valid, the `SAVE` button should be enabled/shown. The 'Add' functionality is working as expected, but I'm facing issues with the 'Update' functionality. The 'SAVE' button is not appearing when all input fields are valid, and I'm unsure why.

<!--upd-->
<div *ngIf="updateEnable" align="center">
  <form align="center" ngNativeValidate>
    id: <input disabled name="id" #updId="ngModel" [value]="selectedStudent.id" [(ngModel)]="selectedStudent.id" class="form-control" required/>

    <br> name: <input name="name" #updName="ngModel" [value]="selectedStudent.name" [(ngModel)]="selectedStudent.name" class="form-control" required [rangeLength]="[3, 30]" />{{updName.valid}}, {{updName.touched}}, {{updName.pristine}}
    <p *ngIf="updName.invalid || updName.errors?.rangeLength">Name must be filled and must be between 3-30 characters long</p>

    <br> year: <input name="year" #updYear="ngModel" [value]="selectedStudent.year" [(ngModel)]="selectedStudent.year" class="form-control" required digits/>{{updYear.valid}}, {{updYear.touched}}, {{updYear.pristine}}
    <p *ngIf="updYear.invalid || updYear.errors?.digits">Year must be filled and must be a number</p>

    <br> semester: <input name="semester" #updSemester="ngModel" [value]="selectedStudent.semester" [(ngModel)]="selectedStudent.semester" class="form-control" required digits/>{{updSemester.valid}}, {{updSemester.touched}}, {{updSemester.pristine}}
    <p *ngIf="updSemester.invalid || updSemester.errors?.digits">Semester must be filled and must be a number</p>

    <br>Major:
    <select name="major" #updMajor="ngModel" [value]="selectedStudent.major" [(ngModel)]="selectedStudent.major" class="form-control" required>{{updMajor.valid}}
              <option class="form-control" value="Computer Science">Computer Science</option>
              <option class="form-control" value="Politic">Politic</option>
              <option class="form-control" value="Accounting">Accounting</option>  
            </select>
    <p *ngIf="updMajor.invalid">Major must be filled</p>

    <br> score: <input name="score" #updScore="ngModel" [value]="selectedStudent.score" [(ngModel)]="selectedStudent.score" class="form-control" required digits [range]="[0, 101]" />{{updScore.valid}}, {{updScore.touched}}, {{updScore.pristine}}
    <p *ngIf="updScore.invalid || updScore.errors?.digits || updScore.errors?.range">Score must be filled, must be a number, and must be between 0-100</p>

    <br> email: <input name="email" #updEmail="ngModel" [value]="selectedStudent.email" [(ngModel)]="selectedStudent.email" class="form-control" required email/>{{updEmail.valid}}, {{updEmail.touched}}, {{updEmail.pristine}}
    <p *ngIf="updEmail.invalid || updEmail.errors?.email">Email must be filled and must contain @ and domain</p>
    <br>

    <div *ngIf="updId.invalid || updName.invalid || updYear.invalid || updSemester.invalid || updMajor.invalid || updScore.invalid || updEmail.invalid">
      <button disabled class="btn btn-warning" title="Cannot save, please check error message above" type="button" (click)="updStudent(updId.value , updName.value, updYear.value, updSemester, updMajor.value , updScore.value, updEmail.value)" data-dismiss="modal">SAVE</button>
    </div>

    <div *ngIf="updId.valid && updName.valid && updYear.valid && updSemester.valid && updMajor.valid && updScore.valid && updEmail.valid">
      <button disabled class="btn btn-warning" type="button" (click)="updStudent(updId.value , updName.value, updYear.value, updSemester, updMajor.value , updScore.value, updEmail.value)" data-dismiss="modal">SAVE</button>
    </div>

    <button class="btn btn-secondary" #notSaved type="button" data-dismiss="modal">CANCEL</button>

  </form>
</div>

Here is the form for inserting data that is functioning correctly.

<form align="center" ngNativeValidate>       
        ID: 
        <input #newId="ngModel" name="id" class="form-control" [(ngModel)]="newId.value" required digits/>Valid?{{newId.valid}}, Clean?{{newId.pristine}}, Touched?{{newId.touched}}
        <p *ngIf="newId.invalid || newId.errors?.digits">ID must be filled and must be numbers</p>

        <br>Name: 
        <input #newName="ngModel" name="name" class="form-control" [(ngModel)]="newName.value" required [rangeLength]="[3, 30]"/>Valid?{{newName.pristine}}, Clean?{{newName.pristine}}, Touched?{{newName.touched}}
        <p *ngIf="newName.invalid || newName.errors?.rangeLength">Name must be filled and must be between 3-30 characters long</p>
        
        <br>Year: 
        <input #newYear="ngModel" name="year" class="form-control" [(ngModel)]="newYear.value" required digits/>Valid?{{newYear.valid}}, Clean?{{newYear.pristine}}, Touched?{{newYear.touched}}
        <p *ngIf="newYear.invalid || newYear.errors?.digits">Year must be filled and must be numbers</p>

        <br>Semester:
        <input #newSemester="ngModel" name="semester" class="form-control" [(ngModel)]="newSemester.value" required digits/>Valid?{{newSemester.valid}}, Clean?{{newSemester.pristine}}, Touched?{{newSemester.touched}}
        <p *ngIf="newSemester.invalid || newSemester.errors?.digits">Semester must be filled and must be numbers</p>"
        
        <br>Major:
        <select #newMajor="ngModel" name="major" [(ngModel)]="newMajor.value" class="form-control" required>Valid?{{newMajor.valid}}, Clean?{{newMajor.pristine}}, Touched?{{newMajor.touched}}
          <option value="Computer Science">Computer Science</option>
          <option value="Politician">Political Science</option>
          <option value="Accounting">Accounting</option>  
        </select>
        <p *ngIf="newMajor.invalid">Major must be filled</p>

        <br>Score: 
        <input #newScore="ngModel" name="score" class="form-control" [(ngModel)]="newScore.value" required digits [range]="[0, 101]">Valid?{{newScore.valid}}, Clean?{{newScore.pristine}}, Touched?{{newScore.touched}}
        <p *ngIf="newScore.invalid || newScore.errors?.digits || newScore.errors?.range">Score must be filled, must be numbers, and must be between 0-100</p>

        <br>Email:
        <input #newEmail="ngModel" name="email" class="form-control" [(ngModel)]="newEmail.value" required email/>Valid?{{newEmail.valid}}, Clean?{{newEmail.pristine}}, Touched?{{newEmail.touched}}
        <p *ngIf="newEmail.invalid || newEmail.errors?.email">Email must contain @ and domain</p>

          <!--if condition invalid-->
          <div *ngIf="newId.invalid || newName.invalid || newYear.invalid || newSemester.invalid || newMajor.invalid || newScore.invalid || newEmail.invalid">
            <br><button disabled title="Cannot save, please check error message above" class="btn btn-primary" type="submit" (click)="addStudent(newId.value, newName.value, newYear.value, newSemester.value, newMajor.value, newScore.value, newEmail.value)">SAVE</button>
          </div>
    
          <!--if condition valid-->
          <div *ngIf="newId.valid && newName.valid && newYear.valid && newSemester.valid && newMajor.valid && newScore.valid && newEmail.valid">
            <br><button class="btn btn-primary" type="submit" (click)="addStudent(newId.value, newName.value, newYear.value, newSemester.value, newMajor.value, newScore.value, newEmail.value)" data-dismiss="modal">SAVE</button>
          </div>

          <button class="btn btn-secondary" data-dismiss="modal">CANCEL</button>

          </form>


<div *ngIf="updateEnable" align="center">
            <form align="center" ngNativeValidate>
            id: <input disabled name="id" #updId="ngModel" [value]="selectedStudent.id" [(ngModel)]="selectedStudent.id" class="form-control" required/>
        
            <br>
            name: <input name="name" #updName="ngModel" [value]="selectedStudent.name" [(ngModel)]="selectedStudent.name" class="form-control" required [rangeLength]="[3, 30]"/>{{updName.valid}}, {{updName.touched}}, {{updName.pristine}}
            <p *ngIf="updName.invalid || updName.errors?.rangeLength">Name must be filled and must be between 3-30 characters long</p>
        
            <br>
            year: <input name="year" #updYear="ngModel" [value]="selectedStudent.year" [(ngModel)]="selectedStudent.year" class="form-control" required digits/>{{updYear.valid}}, {{updYear.touched}}, {{updYear.pristine}}
            <p *ngIf="updYear.invalid || updYear.errors?.digits">Year must be filled and must be a number</p>"  

            <br>
            semester: <input name="semester" #updSemester="ngModel" [value]="selectedStudent.semester" [(ngModel)]="selectedStudent.semester" class="form-control" required digits/>{{updSemester.valid}}, {{updSemester.touched}}, {{updSemester.pristine}}
            <p *ngIf="updSemester.invalid || updSemester.errors?.digits">Semester must be filled and must be a number</p>
        
            <br>Major:
            <select name="major" #updMajor="ngModel" [value]="selectedStudent.major" [(ngModel)]="selectedStudent.major" class="form-control" required>{{updMajor.valid}}
              <option class="form-control" value="Computer Science">Computer Science</option>
              <option class="form-control" value="Political Science">Political Science</option>
              <option class="form-control" value="Accounting">Accounting</option>  
            </select>
            <p *ngIf="updMajor.invalid">Major must be filled</p>
        
            <br>
            score: <input name="score" #updScore="ngModel" [value]="selectedStudent.score" [(ngModel)]="selectedStudent.score" class="form-control" required digits [range]="[0, 101]"/>{{updScore.valid}}, {{updScore.touched}}, {{updScore.pristine}}
            <p *ngIf="updScore.invalid || updScore.errors?.digits || updScore.errors?.range">Score must be filled, must be a number, and must be between 0-100</p>

            <br>
            email: <input name="email" #updEmail="ngModel" [value]="selectedStudent.email" [(ngModel)]="selectedStudent.email" class="form-control" required email/>{{updEmail.valid}}, {{updEmail.touched}}, {{updEmail.pristine}}
            <p *ngIf="updEmail.invalid || updEmail.errors?.email">Email must be filled and must contain @ and domain</p>
            <br>

            <div *ngIf="updId.invalid || updName.invalid || updYear.invalid || updSemester.invalid || updMajor.invalid || updScore.invalid || updEmail.invalid">
              <button disabled class="btn btn-warning" title="Cannot save, please check error message above" type="button" (click)="updStudent(updId.value , updName.value, updYear.value, updSemester, updMajor.value , updScore.value, updEmail.value)" data-dismiss="modal">SAVE</button>
            </div>

            <div *ngIf="updId.valid && updName.valid && updYear.valid && updSemester.valid && updMajor.valid && updScore.valid && updEmail.valid">
              <button disabled class="btn btn-warning" type="button" (click)="updStudent(updId.value , updName.value, updYear.value, updSemester, updMajor.value , updScore.value, updEmail.value)" data-dismiss="modal">SAVE</button>
            </div>
            
            <button class="btn btn-secondary" #notSaved type="button" data-dismiss="modal">CANCEL</button> 

            </form>
        </div>

If you need more snippets or information, feel free to ask. Thank you!

Answer №1

After some tinkering, I found the solution by updating updId.valid to

selectedStudent.id.value == valid
. Surprisingly, only this change was needed for everything to work perfectly :D.

The save button functionality now depends on the validity of input fields - it will be disabled if any field is invalid and enabled when all fields are valid.

<span *ngIf="selectedStudent.id.value == valid && updName.valid && updYear.valid && updSemester.valid && updMajor.valid && updScore.valid && updEmail.valid">
              <button class="btn btn-warning" type="button" (click)="updStudent(updId.value, updName.value, updYear.value, updSemester.value, updMajor.value, updScore.value, updEmail.value)" data-dismiss="modal">SAVE</button>
            </span>

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

Query executed but no results returned

Currently, I am practicing GQL and facing an issue when trying to display data in the Playground. I am attempting to access the jsonplaceholder API to fetch all posts and show them, but encountering the following error: Error: GRAPHQL_FORMAT_ERROR: Expec ...

A step-by-step guide for updating a minor version of Angular with Angular CLI

I've been searching online for the answer to this straightforward question, but can't seem to find it anywhere... In my angular 4 project (made with angular cli), I want to utilize the newly introduced http interceptors in version 4.3. Could so ...

Transforming a detailed JSON structure into a more simplified format with Angular 2

As a newcomer to Angular 2, I find myself encountering a hurdle in filtering unnecessary data from a JSON object that is retrieved from a REST API. Below is an example of the JSON data I am working with: { "refDataId":{ "rdk":1, "refDataTy ...

Regex for US zip code with an optional format

Searching for a regular expression to validate US zip codes. I have come across multiple examples, but none of them cater to the scenario where the zip code is optional. The input field I am working on does not require a zip code, so it should accept a 5 ...

The art of representing objects and generating JSON responses

As I dive into building a web application using NextJS, a versatile framework for both API and user interface implementation, I find myself pondering the best practices for modeling and handling JSON responses. Key Points In my database, models are store ...

Angular: Struggling with Parent Component not recognizing changes in Child Component

Currently, I am facing an issue with my shopping cart functionality. When the website first loads and a user does not have a saved shopping cart, they need to click "add to cart" before one is created. The problem lies in the fact that my app.component doe ...

The ngModel in Angular 2 does not update when a selection is made

Two select options are available, where the second one is dependent on the first: <div class="form-group"> <label class="col-xs-12 col-sm-2 control-label">Vehicle Type:</label> <div class="col-xs-12 col-sm-10"> ...

Clicking the "X" close button on a mat-list removes an item from the user interface

Recently, I utilized the mat-list component to display items on the UI. Each item is accompanied by a close(X) button located on the right-hand side. https://i.stack.imgur.com/1E2ZG.png Html Code <mat-list > <ng-container *ngFor='le ...

Setting up the propTypes for interface in React TypeScript

How can I specify the correct PropTypes for a property that is an interface in TypeScript with PropTypes? Requirements - Implementing both TS and PropTypes. Goal - To have a more precise type definition than PropTypes.any that meets standard eslint an ...

Typescript: Transforming generic types into concrete types

I am utilizing a Generic type type GenericType = { [key: string]: { prop1: string, prop2?: string, prop3?: number, }, }; The purpose of the Generic type is to assist in constructing / validating a new object that I have created. const NewO ...

The check is ineffective: if (isset ($_PHP["form_name"]))

I believe there is an issue with the form validation in the file. It seems that all forms with queries are being executed without proper checks. The code snippet below shows my attempt to address this using if (isset($_POST ['form_name'])), but i ...

The HTML button triggers a function to execute on a different webpage when clicked

I'm facing a straightforward issue that I can't seem to figure out due to my limited experience with Angular and web development. The problem revolves around two components, namely home and dashboard. In the home.component.html file, there's ...

Employing various Class Methods based on the chosen target compiler option

Is there a way to instruct TypeScript to utilize different implementations of methods within the same class, based on the specified target option in the tsconfig.json file? I am currently transitioning one of my scripts to TypeScript to streamline managem ...

Struggling with testing the checkbox when it changes inside the CardHeader Avatar={} component

I've recently implemented a feature similar to the example showcased on MaterialUI's TransferList. However, I'm encountering difficulties accessing a checkbox within the avatar={}. The project utilizes Jest and Enzyme for testing purposes. T ...

Error in Angular 7: ActivatedRoute paramId returns null value

On page load, I am trying to subscribe to my paramsID, but when I use console.log(), it returns null. I am currently working with Angular 7. Here is my TypeScript code: import { Component, OnInit } from '@angular/core'; import { Activat ...

Refreshing Data in Angular Application without Maintaining Previous Success or Error State

I am currently developing an Angular application that requires editing and updating posts. Whenever a user leaves the edit post page and returns to it, I noticed that the data along with the success/error state are maintained. In order to ensure that users ...

Discover the best method for retrieving or accessing data from an array using Angular

In my data processing task, I have two sets of information. The first set serves as the header data, providing the names of the columns to be displayed. The second set is the actual data source itself. My challenge lies in selecting only the data from th ...

Create an interactive Angular form that dynamically generates groups of form elements based on data pulled from

I am currently developing an Angular application and working on creating a dynamic form using Angular. In this project, I am attempting to divide the form into two sections: Person Name and Personal Details. While I have successfully grouped fields for P ...

Invalid Redux store: Element type is not valid; a string type is expected

I am running into an issue while setting up the redux store with typescript for the first time. The error message I am encountering is: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) ...

Mastering the art of mocking modules with both a constructor and a function using Jest

I'm a Jest newbie and I've hit a roadblock trying to mock a module that includes both a Class ("Client") and a function ("getCreds"). The Class Client has a method called Login. Here's the code snippet I want to test: import * as sm from &ap ...