A. Duff
A. Duff

Reputation: 4309

Accessing input field value without ngModel in Angular2/Typescript

I'm using Typescript with Angular2, just like in the Angular2 Tour of Heroes tutorial.

I have an input field that I want to attach a change event to, so that some custom logic can perform when the field is changed. I need to know the field's current value to perform the logic, so I don't want to bind that field with ngModel, as that will override the property before I'm able to retrieve its former value before it was changed.

So I have something like:

<input (change)="handleChange(myObj, $event)" value={{ myObj.myField }}... />

Then in handleChange:

handleChange (obj: MyObjectClass, e: Event) {
  oldValue: number = obj.myField;
  newValue : number = parseInt(e.target.value);

  // Do some logic

  obj.myField = newValue;
}

While this works fine in code, the Typescript compiler is throwing an error error TS2339: Property 'value' does not exist on type 'EventTarget'. on the line newValue : number = parseInt(e.target.value);

Is there a better way of doing this?

Upvotes: 5

Views: 14946

Answers (4)

Madhu Ranjan
Madhu Ranjan

Reputation: 17944

If you see the definition of EventTarget, it is like below,

 interface EventTarget {
   addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
   dispatchEvent(evt: Event): boolean;
   removeEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
 }

it does not contain the value property. so if you want to do it in right way you can use ,

 e.target['value']

Now the reason why there is no value proerty on EventTarget can to support different type of events , for e.g you may use same Event for input type checked and in that case you would like to see checked property.

Upvotes: 2

LeOn - Han Li
LeOn - Han Li

Reputation: 10234

The easiest way is to use the official Get user input from a template reference variable. so it only happens in your Template scope without affecting the Component at all. Something like:

<input (change)="handleChange(myObj, newValue.value)" #newValue />

// Method keep the same
handleChange (obj: MyObjectClass, e: Event) {
  oldValue: number = obj.myField;
  newValue : number = parseInt(e.target.value);

  // Do some logic

  obj.myField = newValue;
}

A bonus is if you need to bind Enter key to the input field, you do not have to write the annoying if($event.keyCode == 13) ..., instead use the Key event filtering feather and do:

(keyup.enter)="onEnter(newvalue.value)"

Upvotes: 1

Ben Richards
Ben Richards

Reputation: 3575

To do validation on input values, you are better off writing a custom validator instead of trying to use change event. That being said, you can pass the input value by using a reference to the input like this:

<input #myInput (change)="handleChange(myInput.value, $event)" value={{ myObj.myField }}... />

Upvotes: 5

Soviut
Soviut

Reputation: 91655

The Angular2 events don't have direct access to the event's target. You really shouldn't be accessing your value via the raw element, you should always be using a binding.

whatever.component.ts

export class WhateverComponent {
    private tempField: any;

    private handleChange(obj: MyObjectClass, e: Event) {
        obj.field = this.tempField;
    }
}

whatever.component.html

<input (change)="handleChange(myObj, $event)" [value]="tempField" />

If you really must access the element, there is the ElementRef class. However, this is a major security risk and you should heed the warning in the documentation:

Permitting direct access to the DOM can make your application more vulnerable to XSS attacks. Carefully review any use of ElementRef in your code. For more detail, see the Security Guide.

Upvotes: 1

Related Questions