Home > Blockchain >  Angular - How to disable or hide submit button if there is no form array
Angular - How to disable or hide submit button if there is no form array

Time:09-23

In Aangular-12, I am implementing dynamic input fields FormArray in Reactive Form. I have this code:

isLoading = false;
isSubmitted = false;
contactInfoForm!: FormGroup;


updateContact() {
  this.contactInfoForm = this.fb.group({
    id: [''],
    current_residential_address: ['', [Validators.required]],
    contacts: this.fb.array([
      this.addContactFormGroup()
    ])
  });
}

addContactFormGroup(): FormGroup {
  return this.fb.group({
    phone_type_id: ['', Validators.required],
    phone_number: ['', [Validators.required, Validators.maxLength(15)]]
  });
}

get fc() {
  return this.contactInfoForm.controls;
};

public addContactButtonClick() {
  const contacts = this.contactInfoForm.get('contacts') as FormArray
  contacts.push(this.addContactFormGroup())
}

get contacts() {
  return this.contactInfoForm.controls['contacts'] as FormArray;
}

getContactsFormArray(): FormArray {
  return this.contactInfoForm.get('contacts') as FormArray;
}

get contactArray(): FormArray {
  return <FormArray > this.contactInfoForm.get('contacts');
}

public removeOrClearContact(i: number) {
  const contacts = this.contactInfoForm.get('contacts') as FormArray
  if (contacts.length > 1) {
    contacts.removeAt(i)
  } else {
    Swal.fire({
      position: 'center',
      icon: 'error',
      title: 'Employee must have at least one Contact Phone No.',
      showConfirmButton: true,
      timer: 10000
    });
    contacts.reset()
  }
}

onSubmitContact() {
  this.isSubmitted = true;

  if (this.contactInfoForm.invalid) {
    return;
  }
  this.isLoading = true;
  this.employeeService.updateContact(this._id, this.contactdata).subscribe(res => {
    this.data = res;
  });
}
<form [formGroup]="contactInfoForm" (ngSubmit)="onSubmitContact()">
  <div class="row">
    <div class="col-12 col-md-12">
      <div class="form-group">
        <label for="current_residential_address">Current Residential Address:<span style="color:red;">*</span></label>
        <textarea rows="2" formControlName="current_residential_address" name="description" type="text" placeholder="22, Alexander Close ..." class="form-control mb-3" required>
                              </textarea>
      </div>
      <div *ngIf="fc.current_residential_address.touched && fc.current_residential_address.invalid">
        <div *ngIf="fc.current_residential_address.hasError('required')">
          <div class="text-danger">
            Current Residential Address is required!
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="row">
    <div formArrayName="contacts" class="col-md-12">
      <div *ngFor="let contact of getContactsFormArray().controls; let i = index" [formGroupName]="i">
        <p>
          <b>Contact Phone : {{i   1}}</b>
        </p>
        <hr>
        <div class="row">
          <div class="col-12 col-md-4">
            <div class="form-group">
              <label for="phone_number">Phone Number:<span style="color:red;">*</span></label>
              <div class="input-group mb-4">
                <ngx-intl-tel-input [cssClass]="'form-control mb-4'" [preferredCountries]="preferredCountries" [enableAutoCountrySelect]="false" [enablePlaceholder]="true" [searchCountryFlag]="true" [searchCountryField]="[SearchCountryField.Iso2, SearchCountryField.Name]"
                  [selectFirstCountry]="false" [selectedCountryISO]="CountryISO.Scotland" [phoneValidation]="true" [separateDialCode]="true" name="phone_number" formControlName="phone_number">
                </ngx-intl-tel-input>
              </div>
            </div>
            <div *ngIf="getContactFormGroup(i).get('phone_number')!.touched && getContactFormGroup(i).get('phone_number')!.invalid">
              <div *ngIf="getContactFormGroup(i).get('phone_number')!.hasError('required')">
                <div class="text-danger">
                  Phone Number is required!
                </div>
              </div>
              <div *ngIf="getContactFormGroup(i).get('phone_number')!.hasError('validatePhoneNumber')">
                <div class="text-danger">
                  Invalid Phone Number!
                </div>
              </div>
            </div>
          </div>
          <div class="col-12 col-md-4">
            <div class="form-group">
              <label for="phone_type_id">Phone Type:<span style="color:red;">*</span></label>
              <ng-select [items]="phonetypes" [selectOnTab]="true" [searchable]="true" bindValue="id" bindLabel="type_name" placeholder="Select Phone Type" [multiple]="false" [clearable]="true" required formControlName="phone_type_id">
              </ng-select>
            </div>
          </div>
          <div class="col-12 col-md-2">
            <div class="form-group">
              <br><button type="button" class="btn btn-danger float-right" (click)="removeOrClearContact(i)"><i class="fas fa-times-circle"></i> Remove</button>
            </div>
          </div>
        </div>

      </div>
    </div>
  </div>

  <div class="card-footer">
    <button type="button" class="btn btn-primary float-right" (click)="addContactButtonClick()"><i class="fas fa-plus-circle"></i> Add</button>
    <button type="submit" class="btn btn-success" [disabled]="isLoading" class="btn btn-success" (click)="contactValidate()">
                      <span *ngIf="isLoading" class="spinner-border spinner-border-sm mr-1"></span>
                      <i class="fa fa-save" aria-hidden="true"></i> Save</button>
  </div>
</form>

I discovered that the submit button is enabled when there is no dynamic input field FormArray.

How do I disable or hide submit button if there is no form array?

Thanks

CodePudding user response:

I guess you should place all validation responsibility inside form.valid, where every inner form will report its validation status to the main form, so the send button will be disabled when form.valid is false.

I made this code below, if want to check it out a working sample here

  import { Component, VERSION } from '@angular/core';
import {
 AbstractControl,
 FormArray,
 FormBuilder,
 FormControl,
 FormGroup,
 Validators,
} from '@angular/forms';

@Component({
 selector: 'my-app',
 template: `
 <div>
   <form [formGroup]="form" (ngSubmit)="save">
      <label for="type">Address:</label>
      <input type="text" formControlName="address"/>

      <button type="button" (click)="addPhone()">add contact</button>

     <div formArrayName="phones"> 
       <div *ngFor="let formContact of getPhonesForm(); let item=index">
         <div [formGroupName]="item">
           <label for="type">type:</label>
           <input id="type" type="text" formControlName="zone"/>
           
           <label for="number">number</label>
           <input id="number" type="text" formControlName="number"/>
         </div>
         
       </div>
     </div> 


   valid  {{form.valid}}
     touched {{form.touched}}
     dirty {{form.dirty}}

      

     <button type="submit" [disabled]="!form.valid">Save</button>
     
   </form>
  elms
   adress => {{form.controls['address'].valid}}
   phones => {{form.controls['phones'].valid}}
 </div>`,
 styleUrls: ['./app.component.css'],
})
export class AppComponent {
 name = 'Angular '   VERSION.major;
 form: FormGroup;

 constructor(private fb: FormBuilder) {
   this.form = fb.group({
     address: [null, [Validators.required]],
     phones: new FormArray([]),
   });

   this.addPhone();
 }

 addPhone(): void {
   const { phones } = this.form.controls;
   (phones as FormArray).push(
     this.fb.group({
       zone: [null, [Validators.required]],
       number: [null, [Validators.required]],
     })
   );
 }

 getPhonesForm(): AbstractControl[] {
   const { phones } = this.form.controls;

   return (phones as FormArray).controls;
 }

 save() {}
}

 

CodePudding user response:

The only form array you have in your code is the contacts form array, so I assume that that's the array you're talking about. If so, you can use one of your several (why so many?) getters:

 <button [disabled]="isLoading || contacts.length === 0">
       Save
  </button>

CodePudding user response:

You can also use the formGroup.get to access the target formArray and check whether there exists a minimum number of dynamic form elements or not.

<button type = "submit" class = "btn btn-success" [disabled] = "isLoading || !contactInfoForm.get('contact.1')"> Save </button>

For your reference, please find a working demo here.

  • Related