【问题标题】:Error: cannot read property 'controls' of null (formArray inside FormGroup inside FormArray inside FormGroup)错误:无法读取 null 的属性“控件”(FormGroup 内的 FormArray 内的 FormArray 内的 FormGroup)
【发布时间】:2021-04-27 09:54:33
【问题描述】:

我有一个表格可以为这些项目添加项目和存储库。添加存储库时,您输入一个 POM URL。我在访问 POM URL 时遇到问题,并且阻止了表单加载。

我收到错误“无法读取 null 的属性‘控件’

(代码在另一台电脑上,所以我会尽力重新创建它)

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>

按原样,这给了我“无法读取 null 的属性‘控件’”错误

如果我将 get pomUrls 更改为以下内容--

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

-- 然后它完美地工作......至少在索引 0 处检索。有了这个,我可以为单个 repo 添加多个 pomUrls,或者使用单个 pomUrl 添加多个 repos。

但是我不能用多个 pomUrls 添加多个 repos。然后它给了我一个错误“找不到带有路径的控件:'repos -> 1 -> pomUrls -> 1'”。所以它不能超过索引 0,这是有道理的。

我的问题是为什么我不能让它工作?为什么 addRepos.at(0).get('pomUrls') 有效,而 addRepos.get('pomUrls') 无效?

这是我第一个使用 Angular 的大项目,我已经坚持了一周。我一直在寻求帮助,用我能想到的各种方式来表达,并在 stackoverflow 上阅读了很多文章和其他问题,但没有运气。

非常感谢任何帮助!

【问题讨论】:

    标签: angular typescript formarray formgroups


    【解决方案1】:

    请在您的模板 html 中将 ? 添加到 pomUrls?.controls

    pomUrls 在运行时的某个时间点未定义。

    ?. 是一个空安全运算符

    【讨论】:

    • 这消除了控制台错误,但是 pomUrls 文本字段没有出现在页面上。关于为什么或如何解决它的任何想法?
    【解决方案2】:

    关于问题

    了解其工作原理的最简单方法是可视化 FormGroup 的值

    下面是FormGroupaddProject 的样子

      {
        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设置为getter,而是使用一个接收索引参数的函数

    编辑 1

    由于我们已删除 pomUrls,您的 addPomUrls 也必须更改

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

    基本上我们正在为项目的特定索引添加一个 pomUrls

    【讨论】:

    • 进行上述更改会使 addPomUrls() 停止工作(以及我未在原始问题中包含的 removePomUrl())。它不再起作用,因为类型“(i:any)=> FormArray”上不存在属性“push”(和“removeAt”)。会有不同的方法来执行我的添加和删除功能吗? 我在原始问题中添加了删除功能,以便您也可以看到它
    • 感谢您添加如何相应地更改 addPomUrls。不幸的是,现在 getPomUrls 正在触发“无法读取未定义的属性'get'”错误。我不明白为什么 this.addRepos.controls[i] 会被认为是未定义的?
    猜你喜欢
    • 1970-01-01
    • 2022-01-12
    • 2019-08-03
    • 2018-09-03
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 2019-05-17
    • 2021-11-09
    相关资源
    最近更新 更多