18

in the below code I want to use the EventEmitter to result in calling the method onlyNewAddedItems.

I defined the EventEmitter instance and the method that emits the event as shown below:

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

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

To bind to third event I did the following:

<h1 (newItemValue) = onlyNewlyAddedItems($event)></h1>

but when I compile the code, I receive the following error

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

4 <h1 (newItemValue) = onlyNewlyAddedItems($event)></h1>                                        
  src/app/app.component.ts:5:16
    5   templateUrl: './app.component.html',
                     ~~~~~~~~~~~~~~~~~~~~~~
    Error occurs in the template of component AppComponent.
    

Please, let me know how to execute the method onlyNewlyAddedItems via EventEmitter.

AppComponent.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);
  }

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

app.component.html:

<h1 #test = customdirective appItemDetails [item]="currentItem">{{currentItem}}  item</h1>
<label>Add an item: <input #newItem></label>
<button (click) = addNewItem(newItem.value)>add new item</button>
<h1 (newItemValue) = onlyNewlyAddedItems($event)></h1>
Yuri
  • 4,254
  • 1
  • 29
  • 46
Amrmsmb
  • 1
  • 27
  • 104
  • 226
  • 4
    This error can happen also when you put the receiving function / variable in the at the parent template on the wrong child tag - Not the child who is emitting. – Uri Gross Jan 06 '22 at 12:04
  • This error can happen also When a typo like Wrong Output variable when emitting – Uri Gross Apr 13 '22 at 07:04

9 Answers9

23

Temporary solution if you want to leave strict template type checking enabled is to wrap $event in $any(). Example:

$any($event)

it should work .. tested on Angular 13x

Fayyaz
  • 247
  • 2
  • 2
  • I would advise against going this way. It's not necessary and weakens your codebase. All typing error messages can be solved by switching to `any` but it is very rare that doing so solves a typing issue. – Peter Nixey Nov 21 '22 at 10:25
5

Check your app.module.ts file and make sure you have the components listed in your container in the declarations.

@NgModule({
   declarations : [
   AppComponent, 
   //your child component
],
...})
  • This fixed it for me when I was dealing with ngx-image-cropper and it's events return complex types defined in their module. – Michael Lang Dec 22 '21 at 17:32
1

To clear the error,

In the onlyNewlyAddedItems method, you are expecting string but you're passing $event from the template. Please try with the below code.

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

But listening inside the component will not work. since these decorators (Input and Output) are used to communicate outside from the component.

1

Check out this StackBlitz demo. Event emitters are meant for passing data to parent component. In the example, you can see that your code works when you are emitting value from a separate child component.

iwontcode
  • 74
  • 3
0

As other answers have already pointed out, the most likely cause is an error in your declarations/exports/imports in your module, so check that first. However, if you can't seem to fix the issues, here's a handy work around (that doesn't use 'any', which you should try to avoid using).

Step 1 - emit your data as an event in your child ts component:

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

//...

this.newItemValue.emit(result as unknown as Event);

Step 2 - Your parent html component is the same as what you already have:

<h1 (newItemValue) = onlyNewlyAddedItems($event)></h1>

Step 3 - your parent ts component will convert the payload into the necessary data type:

  onlyNewlyAddedItems(event: Event) {
    const val = event as unknown as string;
    console.log(`onlyNewlyAddedItems:  ${val}`);
  }

Hope this helps!

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

Change the method parameter datatype from string to any as below. This method works for me.

onlyNewlyAddedItems(val : any) {
console.log("onlyNewlyAddedItems:" + val);
}
ouflak
  • 2,458
  • 10
  • 44
  • 49
Yukesh.M
  • 17
  • 5
-1

You're trying to handle the emitted event in the same component that you emit it from. If I remove everything else from your AppComponent it looks like this:

export class AppComponent {

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

  # Trigger event to be emitted
  addNewItem(val : string) {
    this.newItemValue.emit(val);
  }

  # Attempt to handle event (in the same component?)
  onlyNewlyAddedItems(val : string) {
    console.log("onlyNewlyAddedItems:" + val);
  }
}
<!-- You're emitting the event here -->
<button (click) = addNewItem(newItem.value)>add item</button>

<!-- and trying to capture the event here, 
     in the same component. This won't work -->
<h1 (newItemValue) = onlyNewlyAddedItems($event)></h1>

Your event emitter and handler are both in the same component which I imagine is not what you want. An event is a way of communicating data to parent components.

Your event will be emitted from the AppComponent itself

Your event will not be emitted within the component. It will be emitted on the component, i.e. you would capture it from the app component itself:

<app-component(newItemValue)="onNewItem($event)"></app-component>

Why you're seeing the wrong event type: Event

You can add any made up event handler to any html element and Angular will just assume it's there and cast it to Event. So you think that your typing is wrong but what's acutally happened is that you've added an event handler for an event that may not (probably doesn't) exist.

Peter Nixey
  • 16,187
  • 14
  • 79
  • 133
-1

Try

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

that solved a similar problem for me.

Boris
  • 351
  • 1
  • 3
  • 11
-1

you're in strict mode, just wrap the $event in $any. it'll solve the issue

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 18 '23 at 08:14