Reputation: 5018
I'm new to Angular. I'm trying few simple things. I've an Input field. I just want to detect changes. I want to call some code whenever I type into the field. I checked these articles:
Here's my code:
my-component.component.html
<input [(ngModel)]="text">
my-component.component.ts
import { Component, OnInit, DoCheck } from '@angular/core';
@Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.css']
})
export class MyComponentComponent implements OnInit, DoCheck {
text="hello world";
constructor() { }
ngOnInit() {
}
ngOnChanges(changes: SimpleChanges) {
// changes.prop contains the old and the new value...
}
// ngDoCheck() { // TRIED THIS ALSO
// console.log("Changes detected")
// }
}
Two important information:
I tried DoCheck
also, but this is not what I want. I want to see if only input field's value is changed or not. But ngDoCheck
will be called after every slight change in the rest of the components also as it is using zone.js
( i read this somewhere).
I can't use (keydown)
also as I want to implement validation code later. I want validation to happen as I type-in. But with keydown, i noticed that I've to trigger validation code with some key-press even after the entered value is valid, let's say a Date/Time.
Keeping above two points in mind, please correct me. Here's the stackblitz.
Upvotes: 14
Views: 91772
Reputation: 341
in html
<input type="text" (input)="onChange($event.target.value)">
in component
onChange(value:string){
console.log(value) }
Upvotes: 0
Reputation: 1434
I think all the above answers are correct. I like the getter-setter method though it adds several lines of code. Just in case you'd like to test a third way of tracking changes y forked your code: https://stackblitz.com/edit/angular-myrrqo
It uses @ViewChildren
and a subscription to the valueChanges
observable:
export class MyComponentComponent implements AfterViewInit {
text="hello world";
second="hi angular";
@ViewChildren(NgModel) myInputRef: QueryList<NgModel>;
ngAfterViewInit() {
this.myInputRef.forEach(ref =>
ref.valueChanges.subscribe(val =>
console.log(`${ref.name}'s value changed to ${val}`)
)
);
}
}
In the template:
<input [(ngModel)]="text" name="firstInput">
<input [(ngModel)]="second" name="secondInput">
I added a second input element to show that if you have more than one element with two-way binding you have to use @ViewChildren
. If you only had one element you could use @ViewChild(NgModel) myFirstInput: NgModel;
and the code would be even simpler.
Upvotes: 2
Reputation: 1925
you can use input()
:
Exemple :
HTML :
<input [(ngModel)]="text" (input)="sendTheNewValue($event)">
TS:
let value:string;
sendTheNewValue(event){
this.value = event.target.value;
}
in your exemple : HTML :
<input [(ngModel)]="text" (input)="change($event)">
<div>the input value is : {{text}}</div>
TS:
import { Component, OnInit, DoCheck, SimpleChanges, OnChanges, Input } from '@angular/core';
@Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.css']
})
export class MyComponentComponent implements OnInit, OnChanges {
text="hello world";
@Input() name: String = "abc"
constructor() { }
ngOnInit() {
}
ngOnChanges(changes: SimpleChanges) {
// changes.prop contains the old and the new value...
console.log("Changes detected");
}
change(event){
this.text = event.target.value;
}
// ngDoCheck() {
// console.log("Changes detected");
// }
}
Upvotes: 28
Reputation: 2899
Angular handles the change detection itself. You just need to hook into the logic when it happens. In most cases this will be preferable to using eventlisteners, which are proposed by most other answers in this thread.
Whenever your input is changed, angular accesses the variable the string is set in.
One way to do something when the variable changes would be to use a get
ter and set
ter.
// create an internal variable (do not change manually)
private _text;
// getter function, called whenever the value is accessed
get text(){
console.log("the value was accessed")
return this._text
}
// setter function, called whenever the value is set
set text(text){
this._text = text
console.log("the value was set")
}
I also edited your stackblitz to include an example. https://stackblitz.com/edit/angular-6qvlrh
Everything else remains the same. And you just have to use ngModel on text.
<input [(ngModel)]="text">
Upvotes: 5
Reputation: 4957
These 2 changes are required to track the changes to input:
Working solution:
1. my-component.component.html
<input [(value)]="text" (change)="onChange($event)">
2. my-component.component.ts
import { Component, OnInit, DoCheck } from '@angular/core';
@Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.css']
})
export class MyComponentComponent {
text="hello world";
constructor() {
console.log("Text = " + this.text)
}
onChange(event: any) {
this.text = event.target.value;
console.log("New value = " + event.target.value)
};
}
Upvotes: 2