A Typescript decorator to watch class properties changes
npm install on-property-change --save
class Person {
name: string;
@OnChange('name')
doStuff() {
console.log(`Name has been changed:`, this.name);
}
}
const p = new Person();
p.name = 'John';
p.name = 'Kyle';
Name has been changed: John
Name has been changed: Kyle
The doStuff
method is called after both properties are initialised
class Person {
public name: string;
public age: number;
@OnChange(['name', 'age'])
public doStuff() {
console.log(`${this.name} is ${this.age} years old`);
}
}
const p = new Person();
p.name = 'John';
p.age = 18;
p.age = 22;
John is 18 years old
John is 22 years old
The bulk
flag means to call the method only when all the properties have changed
class Point {
public x: number;
public y: number;
@OnChange(['x', 'y'], { bulk: true })
public move(): void {
console.log(`Move to ${this.x}:${this.y}`);
}
}
const p = new Point();
p.x = '5';
p.x = '3';
p.y = 8; // Move to 3:8
p.y = 16;
p.x = 10; // Move to 10:16
Move to 3:8
Move to 10:16
You can have multiple decorated methods with any combinations of properties
class Person {
name: string;
age: number;
@OnChange('name')
doStuff() {
console.log('change name')
}
@OnChange('age')
doStuff2() {
console.log('change age 1')
}
@OnChange('age')
doStuff3() {
console.log('change age 2')
}
}
const p = new Person();
p.name = 'John';
p.age = 18;
change name
change age 1
change age 2
The doStuff
method can have arguments. They are the same values as the class fields.
class Person {
public name: string;
public age: number;
@OnChange(['name', 'age'])
public doStuff(name: string, age: number) {
console.log(`${name} is ${age} years old`);
}
}
The history
flag allows you to get the previous value of the property.
class Person {
name: string;
@OnChange('name', { history: true })
doStuff(name: PropertyChange<string>) {
console.log(`User has changed name from ${name.previousValue} to ${name.currentValue}`);
}
}
const p = new Person();
p.name = 'John';
p.name = 'Kyle';
User has changed name from undefined to John
User has changed name from John to Kyle
The full metadata looks like this:
export interface PropertyChange<T> {
firstChange: boolean;
previousValue: T;
currentValue: T;
}
@Component({
selector: 'app-person-card',
templateUrl: './person-card.component.html',
styleUrls: ['./person-card.component.css']
})
export class PersonCardComponent {
@Input() name: string;
@OnChange('name')
doStuff() {
// do stuff
}
}