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

Using jest-dom without Jest is definitely an interesting challenge that many developers may

Can anyone help me with extending Typescript interfaces? I have come across a situation that I am trying to solve. In my tests, I am utilizing expect without using Jest directly (I installed it separately and it functions properly). Now, I am interested ...

AngularJS $routeProvider is experiencing difficulties with its routing functionality

I am a beginner with Angular and I'm trying to understand how multiple routes can lead to the same view/templateUrl and controller. This is what I have written: angular .module('mwsApp', [ 'ngAnimate', 'ngCookies&ap ...

When attempting to initiate a new session, Webdriver.io receives an HTML response from selenium

Currently, I am attempting to execute my selenium tests using webdriver.io. However, the test runner is encountering failure when attempting to establish a session: [18:12:36] COMMAND POST "/session" [18:12:36] DATA {"desiredCapab ...

Incoming information obtained via Websocket

Currently, I am working with Angular and attempting to retrieve data from the server using websockets. Despite successfully receiving the data from the server, I am faced with a challenge where instead of waiting for the server to send the data, it retur ...

Initiating a conversation using a greeting in the Javascript bot framework

I am looking to initiate a multi-level, multiple choice dialog from the welcome message in the Bot Framework SDK using JavaScript. I have a main dialog (finalAnswerDialog) that utilizes LUIS for predicting intents, and a multi-level, multiple choice menu d ...

Discover the secret to loading multiple Google charts simultaneously, despite the limitation that Google charts typically only allow one package to load at a time

I currently have a pie chart displaying smoothly on my webpage, but now I am looking to add a treemap as well. The code snippet for the treemap includes the package {'packages':['treemap']}. It has been stated that only one call should ...

Top solution for maintaining smooth navigation across web pages

As I dive into the world of web development, I find myself intrigued by the idea of reusing navigation and banners across multiple web pages. However, despite my research efforts, I have yet to come across a definitive answer. My objective is simple: The ...

The "click" event is only effective for a single use

I am looking for a way to trigger the click event more than once in my project. I attempted using "live" but it didn't work as expected. There are 2 other similar scripts in this Django project. If you have any suggestions on improving this project, p ...

Having trouble updating an array in a mongoose document?

Need help with updating an array in a document by adding or replacing objects based on certain conditions? It seems like only the $set parameter is working for you. Here's a look at my mongoose schema: var cartSchema = mongoose.Schema({ mail: Stri ...

Use include files to wrap content in a div tag

I have a webpage index.html with the following JavaScript scripts: <script type="text/javascript> $(document).ready(function() { $('a.link').click(function() {var url = $(this).attr('href'); $('#content'). ...

Having trouble running Ajax with JavaScript on a Wamp server

Exploring the realm of ajax, I embarked on a journey guided by a YouTube tutorial to construct a basic food search application. The concept was simple - users would input the name of a food item, and if available, its name would be displayed below. On the ...

Weird State / Unusual Effectiveness with NextJS Links

I'm encountering some unusual behavior in a personal project I'm working on. The project is a recipe website with buttons at the top that lead to different pages querying Firebase for recipe data. In the Index.js file, Firestore queries pass pro ...

Show the meta-field mp3 and place it in a lightbox container on the portfolio page

My Current Portfolio Gallery Setup: Currently, my portfolio gallery is displayed in a masonry grid format using the JIG plugin. This grid showcases images from my custom post_type. When clicking on a thumbnail, a lightbox pops up showing the full photo. T ...

Using Selenium to interact with a link's href attribute through JavaScript

New to Java and Selenium, I'm facing difficulties when trying to click on a link with JavaScript in href attribute. Here's the snippet from the page source: href="javascript:navigateToDiffTab('https://site_url/medications','Are y ...

When utilizing Monggose, Angular, and Node, a route containing the deleteOne method repeatedly reports that the object has been successfully deleted, despite the delete count remaining

I've encountered a similar issue to others, but their solutions didn't work for me. I'm working on a small MEAN app with mongoose and facing a problem when trying to delete a user or any other object stored in the collection. The route seems ...

Using Grails to create remote functions with multiple parameters

Currently, I am able to send one parameter to the controller using the code snippet below in Javascript: <g:javascript> var sel = "test"; <g:remoteFunction action="newExisting" method="GET" update="updateThis" params="'sel='+s ...

An error occurred - 0x800a1391 - JavaScript runtime error: The function 'SelectAllCheckBoxes' has not been defined

I'm currently in the process of learning web development and I am trying to incorporate jQuery into my ASP .NET page. Within the header section, I have included the necessary references: <head id="Head1" runat="server"> <link href=" ...

Issues with Typescript and TypeORM

QueryFailedError: SQLITE_ERROR: near "Jan": syntax error. I am completely baffled by this error message. I have followed the same steps as before, but now it seems to be suggesting that things are moving too slowly or there is some other issue at play. ...

Create a new visual masterpiece using Canvas by repurposing an

I am currently working on the following code snippet; export default async function draw(elRef : RefObject<HTMLCanvasElement>, tileData : TileProps) { const canvas = elRef.current!; const ctx = canvas.getContext('2d')!; ctx.clearRect( ...

Is there a way to activate a Superfish jQuery Menu with a click instead of a hover?

After doing some research on the internet, I came across an implementation of Superfish menu by Joel Birch that functions based on onclick instead of hover. I found a link on Github by Karl Swedberg which seems to be what I need. https://gist.github.com/ ...