You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular报错:TypeError: Type 'any'需有返回迭代器的Symbol.iterator方法

解决「TypeError: Type 'any' must have a Symbol.iterator method that returns an iterator」错误

我在实现“用户输入子任务按回车确认,子任务以项目符号列表展示”的功能时,遇到了标题所示错误。为保证演示正常编译,已注释掉HTML中的<ul>和<li>元素。

以下是简化代码:

task-form.component.html

<div mat-dialog-title>Create Task</div>

<mat-dialog-content>
  <form [formGroup]="taskForm" (ngSubmit)="onSubmit()">
    <mat-form-field>
      <mat-label>Title</mat-label>
      <input
        matInput
        formControlName="title"
        type="text"
        placeholder="Enter a title"
      />
    </mat-form-field>

    <mat-form-field>
      <mat-label>Subtasks</mat-label>
      <input
        matInput
        formControlName="subtasks"
        type="text"
        placeholder="Enter a subtask"
      />
      <button
        mat-icon-button
        matSuffix
        (keydown.enter)="addSubtask()"
        (click)="addSubtask()"
      >
        <mat-icon>add</mat-icon>
      </button>
      <div class="vertical-divider" matSuffix></div>
      <button mat-icon-button matSuffix (click)="clearSubtask()">
        <mat-icon>close</mat-icon>
      </button>
      <mat-hint>Press enter to add a subtask</mat-hint>
    </mat-form-field>
  </form>
  <!-- SHOW HERE ALL SUBTASKS-->
  <!-- 
  <ul>
    @for (subtask of subtasksFormControl.value; track subtask.id){
    <li>
      {{ subtask }}
      <button mat-icon-button (click)="editSubtask(subtask)">
        <mat-icon>edit</mat-icon>
      </button>
      <button mat-icon-button (click)="deleteSubtask(subtask)">
        <mat-icon>delete</mat-icon>
      </button>
    </li>
    }
  </ul>-->
</mat-dialog-content>

<mat-dialog-actions>
  <button (click)="onSubmit()" mat-raised-button color="primary" type="submit">
    Create Task
  </button>
</mat-dialog-actions>

task-form.component.ts

export class TaskFormComponent {
  protected readonly Object = Object;
  taskForm!: FormGroup;
  fromPopup = false;
  constructor(
    private fb: FormBuilder,
    @Optional() private dialogRef: MatDialogRef<TaskFormComponent>,
    @Optional()
    @Inject(MAT_DIALOG_DATA)
    public data: { fromPopup: boolean; task: Task }
  ) {}

  ngOnInit() {
    this.fromPopup = !!this.data?.fromPopup;

    this.taskForm = this.fb.group({
      id: this.data?.task?.id,
      title: new FormControl(''),
      subtasks: new FormControl([]),
    });

    if (this.data?.task) {
      this.taskForm.patchValue({
        id: this.data.task?.id,
        title: this.data.task.title,
        subTasks: this.data.task.subtasks,
      });
    }
  }

  public get subtasksFormControl() {
    return this.taskForm.get('subtasks') as FormControl;
  }

  public addSubtask() {
    this.taskForm.value.subtasks;
    console.log(this.taskForm.value.subtasks);
  }

  public clearSubtask() {
    this.taskForm.patchValue({ subtasks: '' });
  }
}

错误原因及修复方案

1. 核心问题:数据类型不一致

  • 初始化时subtasks是数组类型,但clearSubtask方法将其设为空字符串'',导致模板中@for循环尝试迭代非可迭代的字符串类型,触发TypeError。
  • 输入框直接绑定到subtasks数组控件,用户输入的字符串会覆盖数组,进一步加剧类型混乱。

2. 分步修复

(1)拆分输入与存储控件

将输入新子任务的控件和存储子任务数组的控件分离,避免类型冲突:
修改task-form.component.ts中的ngOnInit方法:

this.taskForm = this.fb.group({
  id: this.data?.task?.id,
  title: new FormControl(''),
  newSubtask: new FormControl(''), // 新增:专门用于输入新子任务
  subtasks: new FormControl([]),
});

对应修改HTML中的输入框formControlName:

<input
  matInput
  formControlName="newSubtask"
  type="text"
  placeholder="Enter a subtask"
/>
(2)完善addSubtask方法

实现真正的添加子任务逻辑,同时清空输入框:

public get newSubtaskControl() {
  return this.taskForm.get('newSubtask') as FormControl;
}

public addSubtask() {
  const newSubtask = this.newSubtaskControl.value.trim();
  if (!newSubtask) return;

  // 复制现有子任务数组并添加新项(带唯一id用于track)
  const updatedSubtasks = [...(this.subtasksFormControl.value || [])];
  updatedSubtasks.push({ id: Date.now(), name: newSubtask });
  
  this.subtasksFormControl.setValue(updatedSubtasks);
  this.newSubtaskControl.setValue(''); // 清空输入框
}
(3)修复clearSubtask方法

将清空逻辑改为重置数组而非字符串:

public clearSubtask() {
  this.subtasksFormControl.setValue([]);
}
(4)修正模板循环与回显逻辑
  • 取消注释<ul>部分,调整显示字段为子任务的name属性:
<ul>
  @for (subtask of subtasksFormControl.value; track subtask.id){
  <li>
    {{ subtask.name }}
    <button mat-icon-button (click)="editSubtask(subtask)">
      <mat-icon>edit</mat-icon>
    </button>
    <button mat-icon-button (click)="deleteSubtask(subtask)">
      <mat-icon>delete</mat-icon>
    </button>
  </li>
  }
</ul>
  • 修复patchValue中的键名错误(subTasks改为subtasks),确保已有子任务正确回显:
if (this.data?.task) {
  this.taskForm.patchValue({
    id: this.data.task?.id,
    title: this.data.task.title,
    subtasks: this.data.task.subtasks, // 修正键名大小写
  });
}

内容的提问来源于stack exchange,提问作者coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 06:42:32