Watching the Event Emitters emitted in Child Components?

How should we approach utilizing or observing parent @Output() event emitters in child components?

For instance, in this demo, the child component utilizes the @Output onGreetingChange as shown below:

<app-greeting [greeting]="onGreetingChange | async"></app-greeting>

This setup will function correctly if onGreetingChange emits within the AfterViewInit lifecycle hook.

  ngAfterViewInit() {
    this.onGreetingChange.emit('Hola');
  }

However, this results in an

ExpressionChangedAfterItHasBeenCheckedError
error.

Is there a way to make this work without encountering the error?

I attempted emitting in both the constructor and OnInit. Any suggestions?

Answer №1

If you want to manually trigger the detection of changes, you can do so by calling detectChanges()

It seems that when changing an @Input in a non-conventional way, the change detection mechanism might not pick up on the changes, hence the need to run it manually!

ngAfterViewInit() {
    this.onGreetingChange.emit('Hola');
    this.cdr.detectChanges();
}

Check out the code on stackblitz

Answer №2

Consider using BehaviorSubject in place of EventEmitter. The main benefit is the ability to set an initial value. Check out this example:

https://stackblitz.com/edit/stackblitz-starters-bncmrb?file=src%2Fmain.ts

Main Application

@Component({
  selector: 'app-root',
  imports: [AppChild, AppChildTwo, AsyncPipe],
  standalone: true,
  templateUrl: './app.component.html',
})
export class App implements OnInit, AfterViewInit {
  @Output()
  // onGreetingChange: EventEmitter<string> = new EventEmitter();
  onGreetingChange = new BehaviorSubject('Hola!!');

  greetingTwo!: string;

  constructor() {
    //    this.onGreetingChange.emit('Hola!!');
  }

  ngOnInit() {
    // this.onGreetingChange.emit('Hola!!');
  }

  ngAfterViewInit() {
    // this.onGreetingChange.emit('Hola');
  }
}

HTML

<div><app-greeting [greeting]="onGreetingChange | async"></app-greeting></div>
<div>
  <app-greeting-two (greetingTwo)="greetingTwo = $event"></app-greeting-two>
</div>
<h2>{{ greetingTwo }}</h2>

Child Component One

@Component({
  selector: 'app-greeting',
  standalone: true,
  template: '<h1>{{ greeting }} Everyone!</h1>',
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
})
export class AppChild {
  @Input()
  greeting!: string | null;
}

Child Component Two

@Component({
  selector: 'app-greeting-two',
  standalone: true,
  template: '<h1>AppChildTwo: {{ greetingTwo | async }} Everyone!</h1>',
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  imports: [AsyncPipe],
})
export class AppChildTwo {
  @Output()
  greetingTwo = new BehaviorSubject('Initial greeting TWO');
}

Answer №3

According to the unique source, indicators are also effective in this scenario.

onIndicatorChangeSignal = createSignal(this.onIndicatorChange, {
  initialData: undefined,
});

Here is the custom template:

<app-indicator [indicator]="onIndicatorChangeSignal()"></app-indicator>

Check out the demonstration here.

Answer №4

To prevent the

ExpressionChangedAfterItHasBeenCheckedError
error and for better performance, it is recommended to utilize ChangeDetectionStrategy.OnPush.

@Component({
  selector: 'app-root',
  imports: [AppChild, AsyncPipe],
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <app-greeting [greeting]="onGreetingChange | async"></app-greeting>
  `,
})
export class App implements OnInit, AfterViewInit { 
  @Output()
  onGreetingChange = new EventEmitter<string>();

  ngAfterViewInit() {
    this.onGreetingChange.emit('Hola');
  }}

For a code example, visit https://stackblitz.com/edit/stackblitz-starters-grepmj?file=src%2Fmain.ts

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The module 'angular/common' was not found in the Angular 2 TypeScript

While experimenting with a sample login form in Angular 2, I encountered an issue when trying to import 'Form_Directives' as: import { FORM_DIRECTIVES } from '@angular/common'; An error was displayed stating that the angular/common m ...

Ways to update a single column in an HTML table when there is a change

I'm stuck trying to find a more efficient method for updating a column in an html table without having to reload the entire table. The table consists of player stats, all pulled from my MYSQL database and displayed in the table except for the last col ...

What can be done to prevent an ajax call on keyup when there are no search results?

I have implemented an autofill search feature using .ajax call on keyup event. Currently, it triggers a new call when the user inputs more than 3 characters. However, I want to prevent additional ajax calls once there are no more results, allowing the user ...

Is there a way to prevent a form from automatically submitting once all inputs have been completed? (Using react-hook-form)

After creating a multi-step-form using shadcn, next, zod, and react-hook-form, I encountered an issue where the form is being submitted on step 3 instead of when clicking the submit button. form.tsx const form = useForm<Inputs>({ resolve ...

Event follows activation of trigger click

I've already gone through this post on Stack Overflow about triggering an action after a click event, but none of the solutions I've tried so far have worked. Let's say I have a menu on my webpage like this: <ul class="nav nav-tabs"&g ...

Modifying the editable functionality of grouped rows in Angular-Slickgrid

Looking for help with angular-slickgrid implementation. I need to enable editing of grouped rows (using Formatter: sum for children rows) and pass the values to all children within the same group. How can this be done without changing the references? ...

What is the reason for React.Component being implemented as a function rather than an ES6 class?

After delving into the codebase of React, I made an interesting discovery. When you define a class like class App extends React.Component, you are essentially extending an object that is generated by the following function: function Component (props, cont ...

What steps should I take to address the error message "TypeError: express-validator is not a function

I am currently utilizing express-validator version 6.4.0 and encountering an error when running the server. I have attempted to implement custom validation by organizing separate files for validator, controller, and routes. Here is the primary server file ...

Step-by-step guide on integrating node.js and MySQL to store data from an online form in a database

Currently, I am attempting to insert data into a MySQL database using node.js by clicking the submit button. However, an error message has appeared and despite understanding it somewhat, I am unsure of how to proceed. Any assistance would be greatly apprec ...

Stop useEffect from triggering during the first render

I'm working on implementing a debounce functionality for a custom input, but I'm facing an issue where the useEffect hook is triggered during the initial render. import { useDebouncedCallback } from "use-debounce"; interface myInputProps { ge ...

Troubleshooting Issue with Filtering Nested Object Array Based on Property

At the core of my data structure lies an array of orders, each containing an array of line items. These line items, in turn, are associated with their respective categories. I am currently attempting to filter the order array based on the category ID of th ...

The promise of a MongoDB connection with Node.js returns as 'awaiting fulfillment'

Greetings to all! A few weeks ago, I embarked on the journey of learning javascript, node.js and mongo. As a beginner, I have an interesting task at hand today. My goal is to add a simple document to the mongoDB and perform a conditional check. So here&apo ...

The Firebase Authentication module encountered an uncaught error: [$injector:modulerr]

I encountered a challenge while developing a small task for Gmail user login and logout using Firebase authentication. The issue in my code is Uncaught Error: [$injector:modulerr] The libraries I included are: <script src='https://cdn.firebase.co ...

Angular: Maximizing Output by Extracting Data from Outer and Inner Observables using RxJS

Subscribing to queryParams gives me the item code, but how can I retrieve data from both getItemDetails and getSecuredData at the same time? To avoid using multiple subscribe() functions, I have opted for the mergeMap operator. this.route.queryParams.pip ...

What is the best way to utilize ng-if to conceal a component in AngularJS when a button in a separate component is clicked?

I am facing a challenge with two child components within a parent component. My goal is to hide component1 when a button in component2 is clicked. Below is an illustration of the current code I am handling: Parent Component HTML: <div ng-app='ap ...

Issue - firestore has not been defined (Occurs strictly after the use of "then")

Having an issue: I successfully create fake users in my database, but encounter a problem when starting the 'for' loop. The error I'm facing is: Error adding document: TypeError: Cannot read property 'firestore' of undefined I ...

ng2 inherits from component and expands upon the parent template

I have a component that inherits from a base component. Now, I would like to expand on the template of the base component within the derived component. For example: Template in base component: <div> <button>1</button> </div> ...

The options for answering (True, False, Yes, and No) are not currently visible

I am struggling with displaying buttons for "True", "False", "Yes", and "No" in an appended row. Here is the application: Application To use the application, follow these steps: 1. Open the application and click on the green plus button. A modal window ...

Angular with PHP Integration Success

I'm navigating the realms of Angular and PHP, understanding that Angular is client-side while PHP operates on the server. I'm curious if there's a way to merge these two technologies, as it's all quite unfamiliar territory for me. For ...

Achieve horizontal bar movement by utilizing google.visualization.DataTable in a left-to-right motion

I am exploring the possibility of reversing the direction of a chart(bar) using google.visualization.DataTable. In the current setup, the bar progresses from left to right, but I wish for it to move from right to left instead. Below is what I have attempte ...