Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot assign to read only property 'closed' of object '[object Object]'

Tags:

I've been cracking my head on this for a few days now, but I can't find the reason why this is happening.

So I'm getting the following error message:

TypeError: Cannot assign to read only property 'closed' of object '[object Object]'

enter image description here

So as you can see, it happens in the civilliability-step3.component.ts at the sendProposal function:

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({});   } } 

Useage of the component:

civilliability-detail.component.html

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

I've tried assigning the true value differently, because I figured maybe I can't add it directly to the model, which is an Input. But that didn't help either.

  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));   } 

UPDATE 1: Added 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; } 

UPDATE 2: Show origin of 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;   } } 

And just to give an overview of the structure, to keep us sane:

<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> 

UPDATE 3: Add tabs data: enter image description here

like image 266
Jordec Avatar asked Apr 09 '19 07:04

Jordec


People also ask

Can not assign to read only property of object?

The error "Cannot assign to read only property of object" occurs when we try to change a property of an object that has been frozen or when a property has been defined with Object. defineProperties() . To solve the error, create a copy of the object or array, or set the property to writable .

How do you assign a value to a readonly property in typescript?

Readonly is a typescript keyword that makes the property read-only in a class, interface, or type alias. We make a property read-only by prefixing the property as readonly . We can assign a value to the readonly property only when initializing the object or within a constructor of the class.


1 Answers

I believe this happens because you cannot modify an object that is stored in the state (ngRx), you could try something like this instead:

sendProposal() {   this.store.dispatch(new CloseProposal(Object.assign({}, this.model, {     details: { closed: true }   }))); } 
like image 162
Michael Doye Avatar answered Sep 18 '22 19:09

Michael Doye