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").

  • Sounds like you're looking for [onPush](https://netbasal.com/a-comprehensive-guide-to-angular-onpush-change-detection-strategy-5bac493074a4). – Chris W. Feb 04 '19 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. – user2816157 Feb 04 '19 at 22:28
  • Sorry misunderstood while speed reading through. Anyway that's what [@input/@output](https://stackoverflow.com/questions/41464871/update-parent-component-property-from-child-component-in-angular-2) event emission or a singleton [service](https://angular.io/tutorial/toh-pt4) is for. – Chris W. Feb 05 '19 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)=""`). – user2816157 Feb 05 '19 at 16:38
  • Well using [(scroll)](https://angular.io/api/router/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. – Chris W. Feb 05 '19 at 16:53
  • My scroll event is attached to a DOM element within the component. I'm wondering if there is a way to "isolate" a component from the component tree. I understand that in some situations an event in a component can change another component somewhere else in the tree, but when i know that an event only affects the current component, i don't want angular to check anywhere else for changes. – user2816157 Feb 05 '19 at 18:56
  • That's what I'm saying, if you read the documentation for `(scroll)` class within angular you're interacting with lifecycle events. It's an angular event handler, not standard js/html, so if that specific event is what's firing off the event bubbling, use another method get your scroll event handling outside of the angular lifecycle :) – Chris W. Feb 05 '19 at 19:00

2 Answers2

0

maybe your problem is with eventPropagation

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

to see if it helps

  • Stopping the event propagation won't change the way angular handles the event. https://embed.plnkr.co/HWcQVDkg1EdeeRcCfpVN/ here clicking on "change" console log "parent" and "child" – user2816157 Feb 05 '19 at 08:48
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.

Ferie
  • 1,358
  • 21
  • 36
  • 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 – Murhaf Sousli Jan 08 '20 at 22:52
  • 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). – Ferie Jan 09 '20 at 11:43
  • 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` – Murhaf Sousli Jan 09 '20 at 13:17
  • Starting `ngAfterViewChecked` does not mean that the whole change detection has performed on the parent component, as suggested in this answer https://github.com/angular/angular/issues/7055#issuecomment-364525025 and the following one by the same user. Try avoid using `ngAfterViewChecked`. – Ferie Jan 10 '20 at 16:19
  • 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. – Murhaf Sousli Jan 10 '20 at 16:31
  • Still the answer to your question is the `OnPush` strategy. You can also read the official documentation, if you do not believe the users on GitHub in the official Angular repository. Does the English Grammar is so important in Computer Science? I believe no. – Ferie Jan 10 '20 at 16:36
  • I didn't say I don't believe him, I said (not necessarily true) and you probably understood him out of context, users who comment in the "official" repo doesn't mean what they say is official. I am telling you this for the benefit.. not to argue. – Murhaf Sousli Jan 10 '20 at 16:44