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

使用ngFor嵌套mat-select时出现“Property is read-only”错误排查

解决Angular中ngFor渲染对象数组时ngModel修改属性提示"read-only"的问题

这个错误我之前也碰到过,核心原因是你正在尝试修改的对象属性处于只读状态。通常有这几种场景会导致这个问题:

  • 你的timingOfApptReminders数组里的对象是从API返回的,部分HTTP客户端(比如Angular HttpClient的某些配置)会自动冻结响应对象,防止意外修改原始数据;
  • 你手动用Object.freeze()冻结了这些对象;
  • 如果用了NgRx这类状态管理库,数组里的对象属于不可变状态的一部分,直接修改会触发只读限制。

第一步:确认问题根源

先在组件里加一行代码,检查对象是否被冻结:

console.log(Object.isFrozen(this.timingOfApptReminders[0]));

如果控制台返回true,说明对象确实被冻结了,接下来就需要创建可修改的对象副本。

解决方案:创建可修改的对象副本

在组件初始化或者获取到原始数据后,把每个对象都转成一个新的可修改副本,这样ngModel就能正常修改属性了。你可以用对象扩展运算符...或者Object.assign来实现:

// 假设你是从API或其他地方获取原始数据
const originalTimingData = [
  { daysUntilAppt: 1, hoursUntilAppt: 0, minutesUntilAppt: 0 },
  { daysUntilAppt: 0, hoursUntilAppt: 1, minutesUntilAppt: 0 }
];

// 生成可修改的副本数组
this.timingOfApptReminders = originalTimingData.map(item => ({ ...item }));
// 或者用Object.assign的写法:
// this.timingOfApptReminders = originalTimingData.map(item => Object.assign({}, item));

额外检查:确保模板中的name属性唯一

你的模板里已经用name="daysUntilAppt-{{i}}"这种方式生成了唯一的name属性,这部分是正确的——Angular要求表单控件必须有唯一的name,否则会出现绑定异常。

如果是用了状态管理库(比如NgRx),那直接修改状态里的对象是不符合不可变原则的,这时候你应该通过dispatch对应的action来更新状态,而不是直接用ngModel绑定修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 11:23:11