0

I need your help. I am newbie in Angular Reactive Forms, so I bought a course on Udemy about Angular. But code, which propose my online-teacher isn't working. I have an error in the string '*ngFor="let control of form.get('skills').controls;' with property 'controls' and VS code says next:'Object is possibly 'null'.ngtsc(2531).Property 'controls' does not exist on type 'AbstractControl''. But my teacher hasn't same problem. So what is happened? My Angular version is 12. Can you help me? Thanks a lot! My html code:

<div class="container">
  <form class="card" [formGroup]="form" (ngSubmit)="submit()">
    <h1>Angular Forms</h1>

    <div class="form-control">
      <label>Email</label>
      <input type="text" placeholder="Email" formControlName="email">
      <div
        *ngIf="form.get('email')!.invalid && form.get('email')!.touched" 
        class="validation">
        <small *ngIf="form.get('email')!.errors!.required">Поле не может быть пустым! </small>
        <small *ngIf="form.get('email')!.errors!.email">Введите корректный email!</small>
      </div>
    </div>

    <div class="form-control">
      <label>Пароль</label>
      <input type="password" placeholder="Пароль" formControlName="password">
      <div 
        *ngIf="form.get('password')!.invalid && form.get('password')!.touched"
        class="validation" >
        <small *ngIf="form.get('password')!.errors!.required">
          Поле не может быть пустым 
        </small>
        <small *ngIf="form.get('password')!.errors!.minlength">
          Длина должна быть не менее {{form.get('password')!.errors!.minlength.requiredLength}}.
          Сейчас количество символов {{form.get('password')!.errors!.minlength.actualLength}}
        </small>
      </div>
    </div>

    <div class="card" formGroupName="address">
      <h2>Адрес</h2>

      <div class="form-control">
        <label>Страна</label>

        <select formControlName="country">
          <option value="ru">Россия</option>
          <option value="ua">Украина</option>
          <option value="by">Беларусь</option>
        </select>
      </div>

      <div class="form-control" >
        <input type="text" placeholder="Город" formControlName="city">
      </div>

      <button class="btn" type="button" (click) = "setCapital()">Выбрать столицу</button>
    </div>

    <div class="card">
      <h2>Ваши навыки</h2>
      <button class="btn" type="button" (click)="addSkill()">Добавить умение</button>
      
      <div class="form-control"
      *ngFor="let control of form.get('skills').controls; let idx = index"
      >
        <label></label>
        <input type="text">
      </div>
    </div>

    <button class="btn" type="submit" [disabled]="form.invalid">Отправить</button>

  </form>
</div>

And my ts code:

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.less']
})
export class AppComponent implements OnInit {
  title = 'forms';
  form!: FormGroup;

  ngOnInit() {
    this.form = new FormGroup({
      email: new FormControl('',
        [Validators.email,
         Validators.required]),
      password: new FormControl(null,
        [Validators.required,
         Validators.minLength(8)]),
      address: new FormGroup({
        country: new FormControl('ua'),
        city:new FormControl('', Validators.required)
      }),
      skills:new FormArray([])
    })
  }

  submit() {
    console.log('Form submitted', this.form);
    const formData = { ...this.form.value };

    console.log('Form Data:', formData);

  }

  setCapital(){
    const cityMap = {
      ru: 'Москва',
      ua:'Киев',
      by:'Минск'
    }

    type Key = keyof typeof cityMap;
    const cityKey:Key = this.form.get('address')!.get('country')!.value;
    const city = cityMap[cityKey];

    this.form.patchValue({
      address:{city}
    })
  }

  addSkill(){
    const control = new FormControl('', Validators.required);
    (this.form.get('skills') as FormArray).push(control);
    console.log(this.form.get('skills'));
    
  }
}
Vladimir
  • 79
  • 1
  • 8
  • 1
    The return type of `FormGroup.get()` is the `AbstractControl` interface so you have to cast it to the proper concrete class. If you cannot easily cast to the proper type, just suppress it. – The Head Rush Aug 12 '21 at 13:14
  • Helped this post [Property 'controls' does not exist on type 'AbstractControl' Angular 4](https://stackoverflow.com/questions/46926182/property-controls-does-not-exist-on-type-abstractcontrol-angular-4) and answer from @sunny kashyap – Vladimir Aug 12 '21 at 13:24
  • 1
    **always** you want manage a FormArray use a getter:`get skillsArray(){return this.form.get('skills') as FormArray}` and use `*ngFor="let group of skillsArray.controls"` – Eliseo Aug 12 '21 at 18:07

0 Answers0