0

If there is a parent component and a child, is there a way to trigger an event in the child component without checking the whole component tree.

import { Component } from '@angular/core'

@Component({
    selector: 'my-app',
    template: '<b>{{ text() }}</b><br /><app-child></app-child>'
})
export class AppComponent {
    text() {
        console.log('parent')
        return 'parent'
    }
}

@Component({
    selector: 'app-child',
    template: '<b>{{ text() }}</b><span (click)="change()"> | Change</span>'
})
export class ChildComponent {
    text() {
        console.log('child')
        return 'child'
    }

    change() { }
}

Here, i want that when the change method is called in the child component, that the parent component does not have to check the view (just logging "child" instead of "parent" and "child").

7
  • Sounds like you're looking for onPush. Commented Feb 4, 2019 at 22:22
  • I'm actually looking for the "opposite" of onPush. On push would avoid change detection in the child when an event is triggered from the parent. I want to avoid change detection in the parent when an event is fired in the child. Commented Feb 4, 2019 at 22:28
  • Sorry misunderstood while speed reading through. Anyway that's what @input/@output event emission or a singleton service is for. Commented Feb 5, 2019 at 14:22
  • I'm not sure how input/output bindings or singleton services would help in this situation. I have a large angular app with a component that triggers many events, and it is slow within the app because the whole component tree is checked every time the user scrolls this component (with (scroll)=""). Commented Feb 5, 2019 at 16:38
  • Well using (scroll) is tied into the router for NavigationEnd so that would be expected behavior. Instead maybe attach an event listener directly to the dom object with like HostListener and handle updates to DOM via Renderer2 (assuming that's maybe what you're subscribing for?) but I guess it depends on the whole situation need which isn't quite clear. Sorry can't be more helpful. Commented Feb 5, 2019 at 16:53

2 Answers 2

0

maybe your problem is with eventPropagation

add <b>{{ text() }}</b><span (click)="change(); $event.stopPropagation()"> | Change</span>

to see if it helps

Sign up to request clarification or add additional context in comments.

1 Comment

Stopping the event propagation won't change the way angular handles the event. embed.plnkr.co/HWcQVDkg1EdeeRcCfpVN here clicking on "change" console log "parent" and "child"
0

You need to use changeDetection: ChangeDetectionStrategy.OnPush in the parent component.

It is also recommended to use always (for each component) the OnPush strategy and if needed start the detection manually using detectChanges() from the ChangeDetectorRef.

If you think to use the change detection in an inherited project, the recommendation is to start applying the OnPush strategy from the leaf components, check that everything is still working, then follow the ancestors and go up one level at time to the root.

Here there is a good article about change detection in Angular.

7 Comments

This is not correct, even if you add OnPush to parent component and for each child component, the child component will always trigger its parent change detection
If this is happening in your project, it means that there is something triggering the change detection in your code (an event or an answer from an API call, for example).
I mean this is how it works by design e.g. if a button is clicked in a child component, the parent view will also be checked in ngAfterViewChecked
Starting ngAfterViewChecked does not mean that the whole change detection has performed on the parent component, as suggested in this answer github.com/angular/angular/issues/7055#issuecomment-364525025 and the following one by the same user. Try avoid using ngAfterViewChecked.
His comment is not necessary true! you can refer to articles that explain how the change detection actually works in Angular. It is called ngAfterViewChecked means this function will be called when the view (which has the children components) are checked. and it starts from the component that triggers the detection all the way up to the root. Try it yourself by using a timer and Subject and subscribe using async pipe in the child template, you'll notice that all parent components to the root will log in their ngAfterViewChecked with each time the timer ticks.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.