Guide to capturing emitted values from eventemitter directly in the template

Currently, I am exploring the process of creating binding between a parent and child component using @Input, @Output, and EventEmitter decorators. Below is an example code snippet demonstrating this:

@Output() newItemValue = new EventEmitter<string>();

In this code, I have defined an EventEmitter that will trigger when the method `addNewItem` is called with a string parameter. Inside the `addNewItem` method, the value is emitted like so:

this.newItemValue.emit(val);

To establish a binding with `this.newItemValue`, I made some modifications in the HTML file as shown below:

<button appItemDetails (click) = addNewItem(newItem.value)>add new item</button>
<p (newItemValue)="onlyNewlyAddedItems($event)"></p>

Upon compiling the application, an error was encountered which is outlined below. Kindly share how to properly bind to `this.newItemValue` from the template.

Error:

Failed to compile.

src/app/app.component.html:4:40 - error TS2345: Argument of type 'Event' is not assignable to parameter of type 'string'.

4 <p (newItemValue)="onlyNewlyAddedItems($event)"></p>
                                         ~~~~~~

  src/app/app.component.ts:5:16
    5   templateUrl: './app.component.html',
                     ~~~~~~~~~~~~~~~~~~~~~~
    Error occurs in the template of component AppComponent.
    

app.component.ts:

import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'InputOutputBindings';
  currentItem = 'TV';
  items = ['item1', 'item2', 'item3', 'item4'];

  @Output() newItemValue = new EventEmitter<string>();

  addNewItem(val : string) {
    this.newItemValue.emit(val);
    console.log("add new item:" + val);
    this.items.push(val);
    console.log("add new item:" + this.items);
  }

  onlyNewlyAddedItems(val : string) {
    console.log("onlyNewlyAddedItems:" + val);
  }
}

item-details.directive.ts:

import { Directive, Input, Output, EventEmitter } from '@angular/core';
@Directive({
  selector: '[appItemDetails]',
  exportAs: 'customdirective'
})
export class ItemDetailsDirective {

  @Input() item : string = "";

  constructor() { }

  ngOnInit() {
    console.log("ngOnInit->:" + this.item)
  }

  ngOnChange() {}
}

app.coponent.html:

<h1 #test = customdirective appItemDetails [item]="currentItem">{{currentItem}}  item</h1>
<label>Add an item: <input #newItem></label>
<button appItemDetails (click) = addNewItem(newItem.value)>add new item</button>
<p (newItemValue)="onlyNewlyAddedItems($event)"></p>

Answer №1

Your inquiry has been carefully reviewed.

It appears that there might be a misunderstanding regarding the concept.

In the scenario you presented, the use of EventEmitter seems unnecessary. In cases where there is no parent/child relationship involved, adding new items via a simple button click can suffice.

To address this, I have revamped your example by introducing a test component housing the textbox as requested.

test.component.html

<h1 #test=customdirective appItemDetails [item]="currentItem">{{currentItem}} item</h1>
<label>Add an item: <input #newItem></label>
<button appItemDetails (click) = addNewItem(newItem.value)>add new item</button>

test.component.ts

import { Component, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'test',
  templateUrl: './test.component.html'
})
export class TestComponent {
  @Output() newItemAdded = new EventEmitter<string>();

  title = 'InputOutputBindings';
  currentItem = 'TV';

  addNewItem(value: string) {
    this.newItemAdded.emit(value);
  }
}import { Component, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'test',
  templateUrl: './test.component.html'
})
export class TestComponent {
  @Output() newItemAdded = new EventEmitter<string>();

  title = 'InputOutputBindings';
  currentItem = 'TV';

  addNewItem(value: string) {
    this.newItemAdded.emit(value);
  }
}

Furthermore, the test component has been integrated as a child component in the app component.

app.component.html

<test (newItemAdded)="newItemAdded($event)"></test>
<h3>TV items: </h3>
<div>
  <ul *ngFor="let item of items">
    <li>{{item}}</li>
  </ul>
</div>

app.component.ts

import { Component, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  items = ['item1', 'item2', 'item3', 'item4'];

  newItemAdded(val : string) {
    console.log("onlyNewlyAddedItems:" + val);
    this.items.push(val);
  }
}

A list of items has been added to your parent (app) component for demonstration purposes. The use of EventEmitter becomes relevant here as we need to display newly added items in the parent's list.

Upon clicking the add new item button in the test component, an event is emitted and captured by the app component. Subsequently, the new item is appended to the existing array of items.

Please examine the demo attentively for a better understanding.

View the working demo on StackBlitz.

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

"Versatile TypeScript interface featuring a combination of different data types for its

When dealing with multiple HTML forms, I need to set up inputs and manage their values. The structure of my types is as follows (you can paste it into TypeScript Playground http://www.typescriptlang.org/play to see it in action): interface InputConfig { ...

What is the best way to reduce the size of a Base64/Binary image in Angular6

I utilized the Ngx-Webcam tool to capture images from my camera. My goal is to obtain both high quality and low quality images from the camera. Although this library provides me with Base64 images, it offers an option to reduce the size using imageQuality ...

Why are optional members utilized in a TypeScript interface?

Currently, I am engaged in an online tutorial on typescript (although it is not in English, I will translate the example): interface Message { email: string; receiver?: string; subject?: string; content: string; } The concept of the ...

Components in Angular 5 app hosted on Firebase fail to load

I successfully deployed my Angular 5 app to Firebase using the commands firebase init and firebase deploy. By default, the main page is pulled from the index.html file within the public directory. To ensure that my index.html was displayed, I made a chan ...

The date selected in the date picker does not display in the view until the calendar is opened

I am currently working with two date pickers named startDate and endDate. My goal is to set up a basic date validation system where the start date cannot come after the end date. The main requirement is that if the user selects an end date that is earlier ...

Angular2+ test case indicating lack of NgControl provider

I've been facing an issue while testing an angular component with multiple dependencies. The test case fails with the error: "No Provider for NgControl". Here's the detailed error message: Chrome 66.0.3359 (Mac OS X 10.13.4) configurator compone ...

Modifying the functionality of "use-input" in Vue.js

Currently, I am utilizing vue.js along with typescript to create an input field that allows users to either choose items from a drop-down menu or manually type in their own input. There are various scenarios where custom input might be allowed or where onl ...

The spinner failed to appear within 2000 milliseconds

After submitting the form, I want to display a spinner for 2000 milliseconds. However, my implementation using the setTimeout function is not working as expected. import { Component, OnInit } from '@angu ...

Guidance on extracting values from an array based on the latest month in Angular

I have a list of data: var dataList = [{ "date": "2022-09-08T04:00:00.000Z", "value": "1.70", }, { "date": "2022-08-24T04:00:00.000Z", "value": "1.20", }, { "date": "2022-08-02T04:00:00.000Z", "value": "0.03", }, { ...

Group-level selection in SlickGrid's multi-level grouping feature

https://i.sstatic.net/NE6MQ.png Incorporating a slick grid with a personalized selection model and a unique checkbox selection plugin has been a successful endeavor. Additional group level checkboxes have been included to facilitate toggling selections at ...

Close the menu in Angular 7 by clicking outside of it

I am seeking a way to detect when a click event occurs inside the parent div #menu, regardless of any HTML tags present within it. Using nativeElement.parent did not provide the desired result. Here is the HTML code: <button #toggleButton (click)="to ...

React Hook: Child Component's onComplete Callback Cannot Call Parent Component's Dispatch

I've attempted multiple solutions to address this issue, but none have proven successful. In my scenario, a third-party library makes an asynchronous call to load content for rendering in the DOM. To integrate this functionality, I have a component ...

Implementing child components rendering in a React application using TypeScript

Just a little background information: I am attempting to build a carousel with pagination using ReactJS. Here is the code snippet I currently have: interface HTMLCarouselT { children: Array<JSX.Element> size: number; } const HTMLCarousel = ({ch ...

Using Angular4: Binding to the result of a function in ngFor loop

Consider the following code snippet: <div *ngFor='let loc of user.locations | async'> <div *ngFor='let day of days'> <div *ngFor='let data of get_data_observable(loc, day) | async'> . ...

Having trouble changing the query string in the URL with Angular 4?

My search form includes various filters such as text inputs, checkboxes, and radio buttons. Whenever the user interacts with these filters, the query string in the URL needs to be updated. Consider the following scenario: http://example.com/search?myFilt ...

Showing a notification in Angular 4 following a background request

In my page, I have a list of posts that display comments when clicked. Everything is working well, but now I want to show a message if there are no comments for the selected post. Here's how I tried setting up the template: <li *ngFor="let post of ...

Retrieving the Value of a Member in an Object using Angular

Is there a way to retrieve the value of an object in Angular using a variable as the member identifier? For example: --> my Angular class object: Object1 { name: foo property2: bar } --> my function: myFunction(memberName: string) { return Ob ...

Identify and correct the invalid item within an array form

https://i.sstatic.net/33oNr.png How can I target and focus on an invalid item in a form array? I have attempted the following using nativeElement focus, but I am not able to pinpoint the exact invalid control. if (this.basicForm.invalid) { const ...

After updating next.config, the NextJS + NextAuth middleware doesn't seem to be triggered

I'm currently utilizing <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b0ded5c8c49dd1c5c4d8f0849e81889e87">[email protected]</a> & <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemai ...

Does the inclusion of a d.ts file in a JavaScript npm package constitute a breaking change according to SemVer guidelines?

Is adding a d.ts type declaration file and a new "types" property in the package.json of a JavaScript npm package considered a breaking change? Would it require a major version bump according to SemVer? This situation could go either way. It doesn't ...