user2013
user2013

Reputation: 538

Angular - Cannot get parent component data

I'm passing a function as parameter from parent to child component. When click event is occurred, function of parent component trigger, but all the property of parent component is undefined. For example,

Parent Component

export class AppComponent implements OnInit {
    constructor( private notificationService: NotificationService ) {}

    unreadNotification(): Observable<any> {
        // here this.notificationService is undefined
        console.log( this.notificationService );
    }
}

Parent html

<notification-menu [unread]= "unreadNotification"></notification-menu>

child Component

export class NotificationMenuComponent implements OnInit {
    @Input() updateUnread: Function;
}

child html

<button type="button" class="icon-button" (click)="updateUnread()">
</button>

Now when I click on notification button, unreadNotification is triggered, but value of this.notificationService in console.log is undefined.

How can I solve this?

Upvotes: 1

Views: 475

Answers (3)

sabbir
sabbir

Reputation: 2025

You can use arrow function so that you can use parent component's information. You can try as like as given below.

updateUnreadNotification = () => {
   // by using arrow function you can get notificationService information
   console.log( this.notificationService );
}

Hope your problem will be solve by this.

Upvotes: 1

Michael
Michael

Reputation: 2454

The answer from @nimeresam is good advice - using an @Output is an idomatic way to achieve this.

It's worth noting though, that the reason that your original solution doesn't work is due to the way that javascript handles the this context.

Writing (click)="updateUnread()" is equivalent to saying this.updateUnread() with this being NotificationMenuComponent - as notificationService does not exist on NotificationMenuComponent you get the undefined error.

To have the context of the parent component used, you would need to bind the context to the updateUnread function before passing it into the child component.

This can be achieved either by converting the function to be an arrow functionn, or using Function.bind

See:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind

It's normally a good idea to enable the typescript option for --noImplicitThis to help catch these errors (though unsure if it will detect it in this case)

Upvotes: 2

Nimer Awad
Nimer Awad

Reputation: 4199

You should use @Input() to pass values from parent to child and @Output() to pass values from child to parent.

Child HTML:

<button type="button" class="icon-button" (click)="update()">
</button>

Child Component:

export class NotificationMenuComponent implements OnInit {
    @Output() updateUnread = new EventEmitter<string>();

    update() {
        this.updateUnread.emit("I am working man!");
    }
}

Parent HTML:

<notification-menu (updateUnread)= "unreadNotification($event)"></notification-menu>

Parent Component:

export class AppComponent implements OnInit {
    constructor( private notificationService: NotificationService ) {}

    unreadNotification(dataFromChild: string) {
        console.log(dataFromChild);
    }
}

Upvotes: 2

Related Questions