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

Discussão em 'Angular' iniciado por Jordec, Novembro 11, 2024.

  1. Jordec

    Jordec Guest

    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]'
    ​

    [​IMG]

    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: [​IMG]

    Continue reading...

Compartilhe esta Página