Reputation: 11364
I am using TypeScript Version 2 for an Angular 2 component code.
I am getting error "Property 'value' does not exist on type 'EventTarget'" for below code, what could be the solution. Thanks!
e.target.value.match(/\S+/g) || []).length
import { Component, EventEmitter, Output } from '@angular/core';
@Component({
selector: 'text-editor',
template: `
<textarea (keyup)="emitWordCount($event)"></textarea>
`
})
export class TextEditorComponent {
@Output() countUpdate = new EventEmitter<number>();
emitWordCount(e: Event) {
this.countUpdate.emit(
(e.target.value.match(/\S+/g) || []).length);
}
}
Upvotes: 451
Views: 532724
Reputation: 355
Make a global.d.ts file in your src folder (or wherever you want)
add this code:
interface EventTarget {
value: any
}
Enjoy.
And yes, this is exactly the kind of detail you should NOT be wasting your time on. ⌚⏲⏳💲💲💲
Upvotes: 4
Reputation: 1310
I faced a similar problem and this is how I resolved it. By using this custom generic type
export type DatasetInjector<T, D extends DOMStringMap> = T & {
dataset: D;
};
How does it work?
In DatasetInjector, the generic T specifies the HTML typescript type, such as HTMLInputElement or HTMLTextAreaElement. The second generic D is used to provide missing information about data attributes of the input tag (or any other HTML tag).
Example
Here we are adding the data attribute inputId for HTMLInputElement
// Now this can be used as funciton type for onChange handler for input element
// ChangeEventHandler<DatasetInjector<HTMLInputElement, { inputId: string }>>
export type DatasetInjector<HTMLInputElement, D extends DOMStringMap> = HTMLInputElement & {
dataset: D; // D -> { inputId: string }
};
For more info see my article here Reference link
Upvotes: 0
Reputation: 2301
For those who are getting this error in angular 13, since upgrading from a previous version
The issue for me was I was using the following in my HTML (which was allowed before)
(keyup)="applyFilter($event.target.value)"
The fix for this was:
HTML:
(keyup)="applyFilter($event)"
Component - in my called function:
applyFilter(event: Event) {
const filterValue = (event.target as HTMLInputElement).value;
// ... etc...
}
And now I could use filterValue again as before.
Upvotes: 100
Reputation: 14123
Don't use the workarounds from other answers that involve casting the event, the event target or entirely disabling type checking. It is not safe.
Instead you should "pluck" the value from the HTML element and pass that as an argument instead.
Oversimplified example:
<input #searchBox type="text" (input)="doSearch(searchBox.value)">
doSearch(text: string): void {
}
So if you expand that to the original example, you should get this:
import { Component, EventEmitter, Output } from '@angular/core';
@Component({
selector: 'text-editor',
template: `
<textarea #text (keyup)="emitWordCount(text.value)"></textarea>
`
})
export class TextEditorComponent {
@Output() countUpdate = new EventEmitter<number>();
emitWordCount(text: string) {
this.countUpdate.emit(
(text.match(/\S+/g) || []).length);
}
}
Upvotes: 27
Reputation: 1313
Angular 11+
Open tsconfig.json
and disable strictTemplates
.
"angularCompilerOptions": {
....
........
"strictTemplates": false
}
Upvotes: 8
Reputation: 4736
User TypeScript built in utility type Partial<Type>
In your template
(keyup)="emitWordCount($event.target)"
In your component
emitWordCount(target: Partial<HTMLTextAreaElement>) {
this.countUpdate.emit(target.value./*...*/);
}
Upvotes: 3
Reputation: 3415
Open tsconfig.json
and disable strictDomEventTypes
.
"angularCompilerOptions": {
....
........
"strictDomEventTypes": false
}
Upvotes: 35
Reputation: 4595
In my case, I had:
const handleOnChange = (e: ChangeEvent) => {
doSomething(e.target.value);
}
And the issue was that I did not provide a type argument to ChangeEvent so that it knows e.target
was an HTMLInputElement
. Even if I manually told it that target
was an input element (e.g. const target: HTMLInputElement = e.target
), the ChangeEvent
still didn't know that made sense.
The solution was to do:
// add type argument
const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
doSomething(e.target.value);
}
Upvotes: 43
Reputation: 261
consider $any()
<textarea (keyup)="emitWordCount($any($event))"></textarea>
Upvotes: 22
Reputation: 295
Best way is to use templating => add id to your input and then use it value
<input type="text" #notaryLockup (keyup) = "searchNotary(notaryLockup.value)"placeholder="Entrez des information" >
searchNotary(value: string) {
// your logic
}
this way you will never have Typescript error when strict verification is activated => See angular Docs
Upvotes: 5
Reputation: 186
Use currentValue
instead, as the type of currentValue is EventTarget & HTMLInputElement
.
Upvotes: 0
Reputation: 2293
Since I reached two questions searching for my problem in a slightly different way, I am replicating my answer in case you end up here.
In the called function, you can define your type with:
emitWordCount(event: { target: HTMLInputElement }) {
this.countUpdate.emit(event.target.value);
}
This assumes you are only interested in the target
property, which is the most common case. If you need to access the other properties of event
, a more comprehensive solution involves using the &
type intersection operator:
event: Event & { target: HTMLInputElement }
You can also go more specific and instead of using HTMLInputElement
you can use e.g. HTMLTextAreaElement
for textareas.
Upvotes: 38
Reputation: 3476
Here is the simple approach I used:
const element = event.currentTarget as HTMLInputElement
const value = element.value
The error shown by TypeScript compiler is gone and the code works.
Upvotes: 120
Reputation: 387
Here is another simple approach, I used;
inputChange(event: KeyboardEvent) {
const target = event.target as HTMLTextAreaElement;
var activeInput = target.id;
}
Upvotes: 13
Reputation: 4346
Here is one more way to specify event.target
:
import { Component, EventEmitter, Output } from '@angular/core';
@Component({
selector: 'text-editor',
template: `<textarea (keyup)="emitWordCount($event)"></textarea>`
})
export class TextEditorComponent {
@Output() countUpdate = new EventEmitter<number>();
emitWordCount({ target = {} as HTMLTextAreaElement }) { // <- right there
this.countUpdate.emit(
// using it directly without `event`
(target.value.match(/\S+/g) || []).length);
}
}
Upvotes: 1
Reputation: 24581
You need to explicitly tell TypeScript the type of the HTMLElement which is your target.
The way to do it is using a generic type to cast it to a proper type:
this.countUpdate.emit((<HTMLTextAreaElement>e.target).value./*...*/)
or (as you like)
this.countUpdate.emit((e.target as HTMLTextAreaElement).value./*...*/)
or (again, matter of preference)
const target = e.target as HTMLTextAreaElement;
this.countUpdate.emit(target.value./*...*/)
This will let TypeScript know that the element is a textarea
and it will know of the value property.
The same could be done with any kind of HTML element, whenever you give TypeScript a bit more information about their types it pays you back with proper hints and of course less errors.
To make it easier for the future you might want to directly define an event with the type of its target:
// create a new type HTMLElementEvent that has a target of type you pass
// type T must be a HTMLElement (e.g. HTMLTextAreaElement extends HTMLElement)
type HTMLElementEvent<T extends HTMLElement> = Event & {
target: T;
// probably you might want to add the currentTarget as well
// currentTarget: T;
}
// use it instead of Event
let e: HTMLElementEvent<HTMLTextAreaElement>;
console.log(e.target.value);
// or in the context of the given example
emitWordCount(e: HTMLElementEvent<HTMLTextAreaElement>) {
this.countUpdate.emit(e.target.value);
}
Upvotes: 526
Reputation: 158
fromEvent<KeyboardEvent>(document.querySelector('#searcha') as HTMLInputElement , 'keyup')
.pipe(
debounceTime(500),
distinctUntilChanged(),
map(e => {
return e.target['value']; // <-- target does not exist on {}
})
).subscribe(k => console.log(k));
Maybe something like the above could help. Change it based on the real code. The issue is ........ target['value']
Upvotes: 8
Reputation: 55443
I believe it must work but any ways I'm not able to identify. Other approach can be,
<textarea (keyup)="emitWordCount(myModel)" [(ngModel)]="myModel"></textarea>
export class TextEditorComponent {
@Output() countUpdate = new EventEmitter<number>();
emitWordCount(model) {
this.countUpdate.emit(
(model.match(/\S+/g) || []).length);
}
}
Upvotes: 1