angular error troubleshoot

TypeError: Cannot assign to read only property

This tutorial guides you on how to resolve Error TypeError: Cannot assign to read only property ‘propertyX’ of object ‘[object Object]’. I was trying simple example myself on Components and Databinding and while binding to Custom Events I had stuck with this error.

TypeError: Cannot assign to read only property

core.js:4127 ERROR TypeError: Cannot assign to read only property 'itemAdded' of object '[object Object]'
    at new CreateItemComponent (create-item.component.ts:10)
    at NodeInjectorFactory.CreateItemComponent_Factory [as factory] (ɵfac.js? [sm]:1)
    at getNodeInjectable (core.js:3956)
    at instantiateAllDirectives (core.js:8417)
    at createDirectivesInstances (core.js:7784)
    at ɵɵelementStart (core.js:14528)
    at AppComponent_Template (template.html:2)
    at executeTemplate (core.js:7757)
    at renderView (core.js:7566)
    at renderComponent (core.js:8819)

Angular provides a way for you to emit custom events from the components if you use EventEmitter in components along with @Output directive as shown below. @Output decorator marks a class field as an output property.

The mistake I did was when I declared the class field as an output property, I missed parenthesis “()”  for @Output decorator. The parenthesis is important because it needs to be executed like a function. Also make sure that “Output” is imported from “@angular/core“.

CreateItemComponent (Child Component) class

import { Component, OnInit, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'app-create-item',
  templateUrl: './create-item.component.html',
  styleUrls: ['./create-item.component.css']
})

export class CreateItemComponent implements OnInit {

  @Output itemAdded = new EventEmitter<{itemTitle: string, itemDesc: string}>();
  @Output itemSpecAdded = new EventEmitter<{itemTitle: string, itemSpec: string}>();

  newItemName = '';
  newItemDesc = '';
  newItemSpec = '';

  constructor() { }

  ngOnInit(): void {
  }

  onAddItem() {
    this.itemAdded.emit({
        itemTitle: this.newItemName, 
        itemDesc: this.newItemDesc
    });
  }

  onAddItemSpec() {
    this.itemSpecAdded.emit({
      itemTitle: this.newItemName, 
      itemSpec: this.newItemSpec
    });
  }

}

Basically, I had to fix the following properties defined in the CreateItemComponent (child component) class as shown below. I just added parenthesis for the @Output directive.

  @Output() itemAdded = new EventEmitter<{itemTitle: string, itemDesc: string}>();
  @Output() itemSpecAdded = new EventEmitter<{itemTitle: string, itemSpec: string}>();

Actually, by using @Output directive we are passing data or our own event out of the component.

AppComponent (Parent Component) Template

Note, the DOM properties in the parent component’s template are bound to these output properties that is defined in the child component. The below is the code sneppet from AppComponent (parent component).

<div class="container">
  <app-create-item (itemAdded)="onItemAdded($event)"
                   (itemSpecAdded)="onItemSpecAdded($event)"></app-create-item>

----
----
</div>

Actually, here we are listening for the custom events in the parent component emitted from the child component by binding custom events using property binding.

That’s it. After fixing the way decorators are declared, the error TypeError: Cannot assign to read only property ‘propertyx’ of object ‘[object Object]’ has disappeared.

Hope it helped 🙂

Also See:

References:

guest
0 Comments
Inline Feedbacks
View all comments