【问题标题】:Cannot assign to read only property 'closed' of object '[object Object]'无法分配给对象“[object Object]”的只读属性“已关闭”
【发布时间】:2019-08-30 10:41:59
【问题描述】:

这几天我一直在思考这个问题,但我找不到发生这种情况的原因。

所以我收到以下错误消息:

TypeError:无法分配给对象“[object Object]”的只读属性“已关闭”

如您所见,它发生在 sendProposal 函数的 Civilliability-step3.component.ts 中:

civilliability-step3.component.ts

@Component({
  selector: 'app-civilliability-step3',
  templateUrl: './civilliability-step3.component.html',
  styleUrls: ['./civilliability-step3.component.scss']
})
export class CivilliabilityStep3Component implements OnInit, OnDestroy {
  @Output() modelChange = new EventEmitter<CivilLiabilityRequestType>();
  @Output() onCloseForm = new EventEmitter();
  @Input() model: CivilLiabilityRequestType;

  public formGroup: FormGroup;

  private closedProposalSub: Subscription;

  constructor(private formBuilder: FormBuilder, private store: Store) {}

  ngOnInit() {
    this.buildForm();

    if (this.model !== undefined && this.model.details.closed) {
      disableFormGroup(this.formGroup);
    }

    this.closedProposalSub = this.store
      .select(ProposalsState.closedProposalResult)
      .subscribe(val => {
        if (val !== undefined) {
          this.modelChange.emit(val);
          this.onCloseForm.emit();
        }
      });
  }

  ngOnDestroy() {
    if (this.closedProposalSub && !this.closedProposalSub.closed) {
      this.closedProposalSub.unsubscribe();
    }
    this.store.dispatch(new ResetClosedProposalResult());
  }  

  sendProposal() {
    this.model.details.closed = true;
    this.store.dispatch(new CloseProposal(this.model));
  }

  closeForm() {
    disableFormGroup(this.formGroup);
  }

  private buildForm() {
    this.formGroup = this.formBuilder.group({});
  }
}

组件的用途:

civilliability-detail.component.html

<app-civilliability-step3
          (onCloseForm)="step1.closeForm(); step2.closeForm(); step3.closeForm()"
          [(model)]="model"
          #step3></app-civilliability-step3>

我尝试以不同的方式分配真值,因为我想我可能无法将它直接添加到模型中,即Input。但这也无济于事。

  sendProposal() {
    const detailsModel = this.model.details;
    detailsModel.closed = true; // <-- same error
    this.model.details = detailsModel;

    const tmpModel = this.model;
    tmpModel.details.closed = true; // <-- same error
    this.model = tmpModel;

    // this.model.details.closed = true;
    this.store.dispatch(new CloseProposal(this.model));
  }

更新 1: 添加了 CivilLiabilityRequestType

export interface CivilLiabilityRequestType extends IRequestData {
  details: CivilLiabilityDetailsModel;
  questionnaire: CivilLiabilityQuestionnaireModel;
  comments: CivilLiabilityCommentsModel;
}

export class CivilLiabilityDetailsModel {
  baseReqId: number;

  startDate: string;
  branch: NamedResource;
  fractioning: NamedResource;
  closed: boolean;
}

更新 2: 显示 this.model 的来源:

civilliability-detail.component.ts

export class CivilliabilityProposalDetailComponent implements OnInit, OnDestroy {
  @Input() model: CivilLiabilityRequestType;
  @Input() tab: Tab;
  @Input() tabs: Tab[] = [];
  @Input() selectedTabIndex;
  @Input() idx: number;

  constructor() {}

  ngOnInit() {}

  ngOnDestroy() {
    this.model = getEmptyCivilLiabilityRequest();
  }
}

detail.component.html

<mat-tab *ngFor="let tab of tabs; let idx = index">
...
<app-civilliability-proposal-detail
  [model]="tab.tabData.data"
  [tab]="tab"
  [tabs]="tabs"
  [selectedTabIndex]="selectedTabIndex"
  [idx]="idx"
>
</app-civilliability-proposal-detail>
...
</mat-tab>

detail.component.ts

@Component({
  selector: 'app-detail',
  templateUrl: './detail.component.html',
  styleUrls: ['./detail.component.scss']
})
export class DetailComponent implements OnInit {
  public tabs: Tab[] = [];
  public selectedTabIndex = 0;
  public quote?: QuoteData;
  public quoteModel: QuoteData;
  public originalModel: any[];
  public readonly = false;
  @Input() public requestType;

  constructor(private activeRoute: ActivatedRoute) {}

  ngOnInit() {
    const snapshot = this.activeRoute.snapshot;

    this.originalModel = snapshot.data['model'];
    if (this.originalModel) {
      this.tabs = this.createTabsFromQuoteModel(this.originalModel);
    }
  }

  private createTabsFromQuoteModel(model: any): Tab[] {
    let tabs: Tab[] = [];

    for (const key of Object.keys(model)) {
      const element = model[key];
      let type: RequestTypes;
      let proposalData: IRequestData = {};

      if (key === 'civilLiability') {
        type = RequestTypes.CivilLiability;
        proposalData.type = RequestTypes.CivilLiability;
        proposalData.data = element;
      }

      tabs = [...tabs, { type: type, name: '', tabData: proposalData }];
      proposalData = {};
    }

    return tabs;
  }
}

只是为了概述结构,让我们保持理智:

<app-detail>
  <mat-tab *ngFor="let tab of tabs; let idx = index">
    <app-civilliability-proposal-detail [model]="tab.tabData.data">
      <app-civilliability-step3 [(model)]="model" ></app-civilliability-step3>
      </app-civilliability-step3
    </app-civilliability-proposal-detail>
  </mat-tab
</app-detail>

更新 3: 添加标签数据:

【问题讨论】:

  • CivilLiabilityRequestTypeclosed 属性是只读的,因此无法分配。能否请您显示型号类型?
  • 添加了模型。但我不确定该属性是否在这里是只读的。我可能错了。
  • 从这个角度来看,错误是不言自明的:TypeError: Cannot assign to read only property 'close' of object '[object Object]''。这意味着创建CivilLiabilityRequestType 实例的人将该属性设置为只读。它是在哪里创建的?
  • 如果您在model 以任何方式更改的地方发布civilliability-detail.component.ts 将会很有用
  • 添加了更多可以提供帮助的代码

标签: javascript angular


【解决方案1】:

我相信发生这种情况是因为您无法修改存储在状态 (ngRx) 中的对象,您可以尝试这样的操作:

sendProposal() {
  this.store.dispatch(new CloseProposal(Object.assign({}, this.model, {
    details: { closed: true }
  })));
}

【讨论】:

  • 我将把它标记为正确的解决方案,因为这以某种方式在不同的地方解决了这个问题。但你是对的,你不能修改来自状态的对象。
  • 我不知道 NgRx 状态是只读的.....感谢您的帮助....
  • 天才!谢谢。挣扎了一整天。
  • 我最近遇到了同样的错误,我花了一分钟才发现不仅对我从ngrx商店get的对象进行变异是非法的,而且在对象存储到ngrx之后继续改变对象也是非法的。将对象传递给 ngrx 进行存储后(相当于您的 this.model 此处),我必须制作一个新的本地副本,以免进一步改变 ngrx 所持有的对象作为状态。
  • “NgRx 的第一条规则,不变性。这个 strictStateImmutability 检查验证开发人员是否尝试修改状态对象。” ngrx.io/guide/store/configuration/… 您可以将其关闭,但您应该考虑这是否真的是您想要的。文档中的示例对于定义用于更改状态的 reducer 也很有帮助。
【解决方案2】:

你必须使用 Object.assign 方法来改变对象的值,如下所示,

 Object.assign(target, source);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-12
    • 2019-04-27
    • 2023-03-13
    • 2021-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多