0

I'm trying to make a required validation to my checkboxes.

My TS file :

public colors: Array<any> = [
     { description: 'White', value: 'White' },
     { description: 'Black', value: 'Black' },
     { description: 'Blue', value: 'Blue' },
     { description: 'Green', value: 'Green' },
     { description: 'Yellow', value: 'Yellow' },
     { description: 'Red', value: 'Red' },
];
    
constructor(
    private formBuilder: FormBuilder,
    private heroService: HeroService,
    private toastr: ToastrService
  ) {
  this.fromInit();
}

ngOnInit(): void {}

fromInit() {
  this.heroCreateForm = this.formBuilder.group({
    suitColors: new FormArray([], [Validators.required]),
  });
}

onCheckChange(event) {
  const formArray: FormArray = this.heroCreateForm.get(
    'suitColors'
  ) as FormArray;

  if (event.target.checked) {
    formArray.push(new FormControl(event.target.value));
  } else {
    let i: number = 0;

    formArray.controls.forEach((ctrl: FormControl) => {
      if (ctrl.value == event.target.value) {
        formArray.removeAt(i);
        return;
      }
      i++;
    });
  }
}


invalidSuitColorsMessage() {
   // this function doesn't work
   if (this.suitColors.errors?.required)
      return "You must choose the hero's suit colors";
}

My HTML file :

<div class="main-content">
  <form [formGroup]="heroCreateForm" (ngSubmit)="createHero()">
    <div class="container">

      <div class="input-container-suitColors-input">
        <label><b>Suit colors: </b></label>
        <ng-container *ngFor="let color of colors; let i=index">
          <div class="radio-contatiner">
            <input type="checkbox"
                   [value]="color.value"
                   (change)="onCheckChange($event)">
            {{color.description}}
          </div>
        </ng-container>
      </div>

      <div class="invalid-input-message"
           *ngIf="suitColors.touched && suitColors.invalid">{{invalidSuitColorsMessage()}}</div>

// here is the issue. I'm getting here an error

      <hr>

      <button type="submit"
              class="registerbtn"
              [disabled]="heroCreateForm.invalid">Register</button>
    </div>
  </form>
</div>

Error

Cannot read properties of undefined (reading 'touched')

I do understand why it does work. I search online and didn't find any solution to my issue.

I'm trying to show a message if the required error happens on those checkboxes

Does anyone can take a look and explain to me why does it happen and how should I fix it?

Elikill58
  • 4,050
  • 24
  • 23
  • 45
John
  • 81
  • 1
  • 2
  • 10
  • 1
    Does this answer your question? [Detecting an undefined object property](https://stackoverflow.com/questions/27509/detecting-an-undefined-object-property) – Elikill58 Dec 05 '21 at 20:37
  • The object `suitColors` is undefined, you should check at this. Lot of information about the undefined error are on multiple SO question like [this one](https://stackoverflow.com/q/32317154/10952503), or [this](https://stackoverflow.com/q/28454203/10952503) – Elikill58 Dec 05 '21 at 20:40
  • Hi i didn't really find any way to fix it from those articles How would you make the validation ? – John Dec 05 '21 at 20:45
  • Let me make an answer to explain how to fix it – Elikill58 Dec 05 '21 at 20:46

1 Answers1

0

The error said the variable touched can't be found because the object that should contains it is not defined. In other language it's also called as null. More explaination about undefined

In your case, suitColors is not defined. So there is multiple ways :

  1. You can define it. For example, in the constructor like that:
constructor(private formBuilder: FormBuilder, private heroService: HeroService,
   private toastr: ToastrService, public suitColors: MyObject) {
   this.fromInit();
}

Or as public variable like that :

public suitColors: MyObject;

constructor(private formBuilder: FormBuilder, private heroService: HeroService, private toastr: ToastrService) {
   this.suitColors = new MyObject();
   this.fromInit();
}
  1. Check in the *ngIf before use it. With this way, you should add a check for ALL object. Also, this will work everytime, even if you define object after ngInit.
<div class="invalid-input-message"
           *ngIf="suitColors != null && suitColors.touched && suitColors.invalid"> 
    {{invalidSuitColorsMessage()}}
</div>
Elikill58
  • 4,050
  • 24
  • 23
  • 45