Home > other >  Dependency between a textbox and a checkbox, multiple records
Dependency between a textbox and a checkbox, multiple records

Time:06-16

I made a stackblitz for this, so I can explain easier.

import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormService } from './form.service';
import {
  FormArray,
  FormBuilder,
  FormControl,
  FormGroup,
  ValidationErrors,
  Validators,
} from '@angular/forms';
import { Injectable } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
@Injectable({
  providedIn: 'root',
})
export class AppComponent {
  form: FormGroup;
  orders = [];
  formSubmitAttempt: boolean;
  ddlRecords: any[] = [];
  ddlTariff: any[] = [];

  formMultiple: FormGroup = this.formBuilder.group({
    ddlRecords: [],
    items: this.formBuilder.array([]),
  });

  constructor(
    private formBuilder: FormBuilder,
    private formService: FormService
  ) {}

  ngOnInit(): void {
    this.getDdlData();
    this.ddlRecords = this.formService.getDropdownRecords();
    this.formMultiple.controls.ddlRecords.patchValue(this.ddlRecords[0].id);
    let cucu: FormGroup = this.createEmptyFormGroupItem();
    this.items.push(cucu);
  }

  ddlRecordsChange(): void {
    const actualFormsLength: number = this.formMultiple.value.items.length;
    const newFormsLength: number = this.formMultiple.value.ddlRecords;

    this.updateFormItems(actualFormsLength, newFormsLength);
    this.getDdlData();
  }

  private updateFormItems(actualFormsLength, newFormsLength): void {
    const itemsToAdd = newFormsLength - actualFormsLength;
    console.log('itemsToAdd', itemsToAdd);
    if (itemsToAdd > 0) {
      for (var i = 0; i < itemsToAdd; i  ) {
        this.items.push(this.createEmptyFormGroupItem(actualFormsLength   i));
      }
    } else {
      for (var i = 0; i > itemsToAdd; i--) {
        this.items.removeAt(this.items.length - 1);
      }
    }
  }

  get items(): FormArray {
    return this.formMultiple.controls['items'] as FormArray;
  }

  private createEmptyFormGroupItem(id: number = 0): FormGroup {
    console.log('id', id);
    return this.formBuilder.group({
      Id: id,
      title: new FormControl('', [Validators.required]),
      ddlTariff: new FormControl(this.ddlTariff[0].id, [Validators.required]),
      exNo: new FormControl(''),
      isDeRe: new FormControl(''),
    });
  }

  getDdlData() {
    this.ddlTariff = this.getTariffs();
  }

  getTariffs(max: number = 5): { id: number; title: string }[] {
    const recordsArray: { id: number; title: string }[] = [];
    for (let i = 1; i <= max; i  ) {
      recordsArray.push({ id: i, title: `tariff ${i}` });
    }
    //console.log('recordsArray.count = '   recordsArray.length);
    return recordsArray;
  }

  submit() {
    console.log(
      'the problem is that the selected dropdown id is not in the submitted obj list'
    );
    console.log(this.items.value);
  }
}

The idea is that this is a List of Multiple Records that we are saving in the db. To get the rest of the records, you can change the Records dropdown.

Goal 1: DeRe checkbox checked -> clear ExNo textbox, and set ExNo textbox Enabled = false (on the same record)

Goal 2: DeRe checkbox unchecked -> set ExNo textbox Enabled = true (on the same record)

<form [formGroup]="formMultiple" (ngSubmit)="submit()">
  <select
    formControlName="ddlRecords"
    
    (ngModelChange)="ddlRecordsChange()"
  >
    <option *ngFor="let record of ddlRecords" [value]="record.id">
      {{ record.name }}
    </option>
  </select>
  <br /><br /><br /><br /><br />
  <div formArrayName="items" *ngFor="let item of items.controls; let i = index">
    <div  [formGroupName]="i">
      <div
        
        [ngClass]="{ 'has-error': formSubmitAttempt && item.invalid }"
      >
        <label>* Title</label>
        <input formControlName="title"  />
      </div>

      <div >
        <label>Tariff</label>
        <select  formControlName="ddlTariff">
          <option *ngFor="let item of ddlTariff" [value]="item.id">
            {{ item.title }}
          </option>
        </select>
      </div>

      <div>
        <label>ExNo</label>
        <input formControlName="exNo"  type="number" />
      </div>
      <div>
        <label>DeRe</label>
        <input formControlName="isDeRe"  type="checkbox" />
      </div>
      <br /><br />
    </div>
  </div>

  <br /><br />
  <button>save list of objects</button>
</form>

Basically something like this, but for each row:

 if (isItChecked)
            {
                Txt.Text = "";
                Txt.Enabled = false;
                
            }
            else 
            {
                Txt.Enabled = true;
            }

My biggest issue is how to differentiate between rows and how to identify the pair of controls (the cb and the textbox that are going to be the same record)

Note: each record can have different "settings" for ExNo and DeRe

I wouldn't mind if the disabled textbox looked different, but this is not something very important

CodePudding user response:

You can subscribe to the changes of isDeRe control and update the state of the exNo control when you create new FormGroup in your createEmptyFormGroupItem, e.g.:

  private createEmptyFormGroupItem(id: number = 0): FormGroup {
    console.log('id', id);
    let exNoControl = new FormControl('');
    let isDeReControl = new FormControl(false);

    isDeReControl.valueChanges.subscribe((value: boolean) => {
      if (value) {
        exNoControl.setValue('');
        exNoControl.disable();
      } else {
        exNoControl.enable();
      }
    })

    return this.formBuilder.group({
      Id: id,
      title: new FormControl('', [Validators.required]),
      ddlTariff: new FormControl(this.ddlTariff[0].id, [Validators.required]),
      exNo: exNoControl,
      isDeRe: isDeReControl,
    });
  }

Note that you should follow good practices and make sure to unsubscribe the observables in the OnDestroy part of the component lifecycle to avoid potential memory leaks, but this is out of the scope of the question as there multiple different ways to do this and multiple tutorials explaining this.

  • Related