Ошибка: не удается прочитать свойство ‘controls’ null (FormArray внутри FormGroup внутри FormArray внутри FormGroup)

#angular #typescript #formarray #formgroups

#angular #машинопись #formarray #formgroups

Вопрос:

У меня есть форма для добавления проектов и репозиториев для этих проектов. При добавлении репозитория вы вводите URL-адрес POM. У меня возникли проблемы с доступом к URL-адресам POM, и это мешает загрузке формы.

Я получаю сообщение об ошибке «Не удается прочитать свойство ‘controls’ с нулевым значением

(Код находится на другом компьютере, поэтому я воссоздам его как можно лучше)

TS

 this.addProject = new FormGroup({
  ...
  repos: new FormArray([
    new FormGroup({
      ...
      pomUrls: new FormArray([new FormControl()])
    })
  ])
});

addRepo(): void {
  this.addRepos.push(new FormGroup({
    ...
    pomUrls: new FormArray([new FormControl()])
  }));
}

get addRepos(): FormArray {
  return this.addProject.get('repos') as FormArray;
}

get pomUrls() {
  return this.addRepos.get('pomUrls') as FormArray;
}

addPomUrls() {
  const control = new FormControl();
  this.pomUrls.push(control);

removePomUrl(index: number): void {
  this.pomUrls.removeAt(index);
}
 

HTML

 <ng-container formArrayName="pomUrls">
  <div *ngFor="let _ of pomUrls.controls; index as i; count as c;">
    <las-ux-textfield [label]="'POM URLs'" [formControlName]="i"></las-ux-textfield>
    <div clss="button-container">
      <las-ux-button [id]="'addPom'   i" ... (click)="addPomUrls()"> </las-ux-button>
      <las-ux-button *ngIf="c > 1" [id]="'removePom'   i" ... (click)="removePomUrl(i)"> </las-ux-button>
    </div>
  </div>
</ng-container>
 

Итак, как есть, это дает мне ошибку «не удается прочитать свойство ‘controls’ с нулевым значением»

Если я изменю get pomUrls на следующее —

 get pomUrls() {
  return this.addRepos.at(0).get('pomUrls') as FormArray;
 

— тогда это работает perfectly…at по крайней мере, для извлечения с индексом 0. С помощью этого я могу добавить несколько pomUrls для одного репозитория или добавить несколько репозиториев с одним pomUrl.

НО я не могу добавить несколько репозиториев с несколькими pomUrls. Затем он выдает мне сообщение об ошибке «не удается найти элемент управления с помощью path: ‘repos -> 1 -> pomUrls -> 1′». Таким образом, он не может выйти за пределы индекса 0, что имеет смысл.

Мой вопрос в том, ПОЧЕМУ я не могу заставить это работать? Почему addRepos.at (0).get(‘pomUrls’) работает, а addRepos.get(‘pomUrls’) нет?

Это мой первый большой проект с Angular, и я застрял на этом на неделю. Я искал помощь, формулируя это всеми возможными способами, и прочитал множество статей и других вопросов здесь, в stackoverflow, но безуспешно.

Любая помощь приветствуется!

Ответ №1:

Пожалуйста, добавьте ? pomUrls?.controls в свой шаблон html.

pomUrls не определено в какой-то момент времени выполнения.

?. является нулевым оператором безопасности

Комментарии:

1. Это устраняет ошибку консоли, но тогда текстовое поле pomUrls не отображается на странице. Есть мысли о том, почему или как это исправить?

Ответ №2:

О проблеме

Самый простой способ понять, как это работает, — визуализировать значение FormGroup

Ниже показано, как FormGroup addProject будет выглядеть ваш for

   {
    repos: [
      {
         pomUrls: ['']
      }
    ]
  }
 

и это для addRepos

  [
   {
      pomUrls: ['']
   }
 ]
 

Теперь рассмотрим приведенный ниже код

   return this.addRepos.at(0).get('pomUrls') as FormArray;
 

Приведенный выше код принимает первый элемент ( .at(0) ) и извлекает pomUrls свойство. В принципе, если бы это был простой JS-код, это было бы myFormGroup[0].pomUrls . как вы уже упоминали, это работает отлично.

Теперь давайте попробуем этот код

   addRepos.get('pomUrls')
 

Теперь вышесказанное похоже на попытку сделать следующее

   const addProject =   {
repos: [
  {
     pomUrls: ['']
  }
]
  }
  const addRepos = addProject.repos;
  console.log(addRepos.pomUrls) 

Так что, как правило, это похоже на попытку извлечь свойство из массива без получения определенного индекса первым

Как решить?

Вы можете использовать много способов приблизиться к этому. Вы можете рассмотреть ниже

 getPomUrls(i) {
  return this.addRepos.controls[i].get('pomUrls') as FormArray;
}
 

В приведенном выше вместо установки pomUrls в качестве средства получения используйте функцию, которая принимает аргумент индекса

Редактировать 1

Поскольку мы удалили pomUrls ваше addPomUrls , вам также придется изменить

     addPomUrls(i) {
      const control = new FormControl();
      this.getPomUrls(i).push(control)
    }
 

По сути, мы добавляем pomUrls для определенного индекса проекта

Комментарии:

1. внесение вышеуказанного изменения останавливает работу addPomUrls() (и removePomUrl(), который я не включил в исходный вопрос). Это больше не работает, потому что свойства ‘push’ (и ‘RemoveAt’) не существуют для типа ‘(i: any) => FormArray’. Есть ли другой способ выполнить мои функции добавления и удаления? Я добавил функцию удаления в свой первоначальный вопрос, чтобы вы тоже могли ее увидеть

2. Спасибо, что добавили, как соответствующим образом изменить addPomUrls. К сожалению, теперь getPomUrls вызывает ошибку «Не удается прочитать свойство ‘get’ неопределенного». Я не могу понять, почему this.addRepos.controls[i] будет считаться неопределенным?