user584018
user584018

Reputation: 11364

Property 'value' does not exist on type 'EventTarget'

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

Answers (19)

Niranjan
Niranjan

Reputation: 1844

$any($event.target ).value should do the trick.

Upvotes: 5

Bobby Connolly
Bobby Connolly

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

just-be-weird
just-be-weird

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

James D
James D

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

Steven Liekens
Steven Liekens

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

Rahi.Shah
Rahi.Shah

Reputation: 1313

Angular 11+

Open tsconfig.json and disable strictTemplates.

 "angularCompilerOptions": {
    ....
    ........
    "strictTemplates": false
  }

Upvotes: 8

Monfa.red
Monfa.red

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

Salad.Guyo
Salad.Guyo

Reputation: 3415

Angular 10+

Open tsconfig.json and disable strictDomEventTypes.

  "angularCompilerOptions": {
    ....
    ........
    "strictDomEventTypes": false
  }

Upvotes: 35

Lewis
Lewis

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

Ali Maher
Ali Maher

Reputation: 261

consider $any()

<textarea (keyup)="emitWordCount($any($event))"></textarea>

Upvotes: 22

Idriss Sakhi
Idriss Sakhi

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

Charles Zhao
Charles Zhao

Reputation: 186

Use currentValue instead, as the type of currentValue is EventTarget & HTMLInputElement.

Upvotes: 0

belvederef
belvederef

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

Torsten Barthel
Torsten Barthel

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

Burak Odabaş
Burak Odabaş

Reputation: 387

Here is another simple approach, I used;

    inputChange(event: KeyboardEvent) {      
    const target = event.target as HTMLTextAreaElement;
    var activeInput = target.id;
    }

Upvotes: 13

qiAlex
qiAlex

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

smnbbrv
smnbbrv

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

Ahmed
Ahmed

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

micronyks
micronyks

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

Related Questions