使用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
相关产品推荐
相关产品推荐

