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

Angular Material自动补全搜索功能报错:TypeError无法读取undefined的'name'属性

解决Angular Material自动补全报错:TypeError: 无法读取undefined的'name'属性

我来帮你排查这个Angular Material自动补全的报错问题~首先咱们先拆解下报错的根源,再一步步修复:

问题根源分析

你遇到的TypeError: 无法读取undefined的'name'属性,主要来自两个地方:

  1. 过滤后的数组存在undefined元素:你的filter函数里用filteredData[i] = this.persons[i]给数组赋值,当循环中某个person不满足过滤条件时,filteredData对应索引的位置就会是undefined。后续*ngFor遍历这个数组时,碰到undefined的项,访问person.name自然就报错了。
  2. 未处理初始状态下的空值:如果persons是异步加载的,初始值为undefined,filter函数会直接返回undefined,导致filteredOptions流中出现空值,模板渲染时同样会触发报错。

分步修复方案

1. 修正过滤数组的赋值逻辑

放弃用索引赋值的方式,改用push()添加符合条件的元素,确保数组里不会出现undefined:

filter(val: string): any[] {
  const filteredData = [];
  // 如果persons还没加载,直接返回空数组
  if (!this.persons) return [];

  const searchTerm = val.toLowerCase();
  // 用for...of遍历更简洁直观
  for (const person of this.persons) {
    // 简化条件判断,把空值/undefined的情况合并
    if (this.basis.value === "name" || !this.basis.value) {
      if (person.name.toLowerCase().includes(searchTerm)) {
        filteredData.push(person);
      }
    } else if (this.basis.value === "id") {
      // 注意:如果id是数字类型,要先转成字符串再做小写匹配
      if (person.id.toString().toLowerCase().includes(searchTerm)) {
        filteredData.push(person);
      }
    }
  }
  return filteredData;
}

2. 给Observable添加初始值

在ngOnInit里,用startWith操作符给filteredOptions设置初始空数组,确保模板初始渲染时不会拿到undefined:

filteredOptions: Observable<any[]>;
ngOnInit() {
  this.filteredOptions = this.name.valueChanges.pipe(
    map(val => this.filter(val)),
    // 初始时返回空数组,避免模板报错
    startWith([])
  );
}

3. 模板添加空值保护(双重保险)

在模板里访问person.name前,用可选链操作符?.做保护,就算数组里不小心出现undefined,也不会触发报错:

<input type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="name" [matAutocomplete]="auto">

<mat-autocomplete #auto="matAutocomplete">
  <!-- 去掉多余的*ngIf="filteredOptions",startWith已经确保有初始值 -->
  <mat-option *ngFor="let person of filteredOptions | async" [value]="person?.name">
    {{person?.name}}
  </mat-option>
</mat-autocomplete>

4. 额外优化建议

  • 给persons定义类型并初始化为空数组,比如:persons: Person[] = [];,从根源避免undefined的情况
  • 可以用数组的filter方法简化过滤逻辑,代码更简洁易读:
// 假设你有Person类型定义:interface Person { name: string; id: string | number; }
filter(val: string): Person[] {
  if (!this.persons || !val) return this.persons;

  const searchTerm = val.toLowerCase();
  return this.persons.filter(person => {
    if (this.basis.value === "name" || !this.basis.value) {
      return person.name.toLowerCase().includes(searchTerm);
    } else if (this.basis.value === "id") {
      return person.id.toString().toLowerCase().includes(searchTerm);
    }
    return false;
  });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:36:48