I want to monkey patch the ngOnChanges life cycle hook so that I can execute some custom logic whenever ngOnChanges is executed. With the following code snippet I'm already able to to this:
export function changes$<T extends Record<string, any>>(target: any) {
const inputs = target.constructor.ɵcmp.inputs;
const origNgOnChanges = target.constructor?.prototype?.ngOnChanges;
const origNgOnInit = target.constructor?.prototype?.ngOnInit;
target.constructor.prototype.ngOnInit = function (): void {
const simpleChangesToPass: TypedSimpleChanges<T> = {};
Object.keys(inputs)
.map((key) => inputs[key])
.forEach((inputKey) => {
simpleChangesToPass[inputKey] = new SimpleChange(
this[inputKey],
this[inputKey],
true
);
});
console.log(mapChanges(simpleChangesToPass));
if (origNgOnInit) {
origNgOnInit.apply(target.constructor.prototype);
}
};
// overwrite the original ngOnChanges life cycle hook
target.constructor.prototype.ngOnChanges = function (
simpleChanges: TypedSimpleChanges<T>
): void {
console.log('ngOnChanges ', simpleChanges);
console.log(simpleChanges);
const mappedChanges = mapChanges(simpleChanges);
if (mappedChanges === undefined) {
return;
}
console.log(mapChanges(simpleChanges));
if (origNgOnChanges) {
origNgOnChanges.apply(target.constructor.prototype, [simpleChanges]);
}
};
return stream$.asObservable().pipe(
filter(isNotUndefined),
scan((acc, curr) => ({ ...acc, ...curr }), {} as T),
distinctUntilChanged((previous: T, current: T) => {
const keys = Object.keys(current);
return keys.every((key) => {
return current[key] === previous[key];
});
})
);
}
However I face the Problem that if a new Input arrives I do not get the new value logged. Only after a second time a new input arrives I see in the log the value of the previous change. So I'm always one value behind the actual current value and I do not spot the issue.
Repro/Stackblitz: https://stackblitz.com/edit/stackblitz-starters-2rvjvp?file=src%2Fmain.ts
Hint: console.log is just a very simplified example of executing "custom logic"