Skip to content

Instantly share code, notes, and snippets.

@dmorosinotto
Last active October 16, 2019 19:13
Show Gist options
  • Save dmorosinotto/c74f2c0d2e4cef4790815ec3b0684cc7 to your computer and use it in GitHub Desktop.
Save dmorosinotto/c74f2c0d2e4cef4790815ec3b0684cc7 to your computer and use it in GitHub Desktop.
Angular call-apply Pipe Solve Perf Problem of calling function inside template/interpolate -> sample: https://stackblitz.com/edit/angular-call-aply-pipe
import { Pipe, PipeTransform } from '@angular/core';
const error_this = function(){ console.error("DON'T USE this INSIDE A FUNCTION CALLED BY | call OR | apply IT MUST BE A PURE FUNCTION!"); return false; }
const NOTHIS = !('Proxy' in window)
? Object.seal({})
: new Proxy({}, {
get: error_this,
set: error_this,
deleteProperty: error_this,
has: error_this,
});
@Pipe({
name: 'call',
pure: true
})
export class CallPipe implements PipeTransform {
transform(value: any, args?: Function): any {
return args.call(NOTHIS,value);
}
}
@Pipe({
name: 'apply',
pure: true
})
export class ApplyPipe implements PipeTransform {
transform(fn: Function, ...args: any[]): any {
return fn.apply(NOTHIS, args);
}
}
<hello name="{{ name }}"></hello>
<p>
Start editing to see some magic happen :)
</p>
<article>
<header>TEST PIPE | call </header>
<aside>
SOMETHING {{ name | call: doSomething }}<br/>
SOMETHING OBJ {{ obj.x | call: doSomething }}<br/>
</aside>
</article>
<article>
<header>TEST PIPE | apply</header>
<aside>
DOAPPLY {{ doParams | apply : name : obj : obj.x }}<br/>
DOAPPLY OBJ {{ doParams | apply: obj }}<br/>
</aside>
</article>
<article>
<header>PERF PROBLEM
<p><b>Calling function in interpolation -> run on EVERY CHANGE DETECTION CYCLE!!!</b>
<i> Even if you Change X or Y that is not used in doSomething(name,...)!!!</i></p>
</header>
RENDER ALWAYS -> {{ doSomething(name, 'EVERY change detention') }}
<!-- SOME WAY THAT CAUSE CHANGE DETENCION -->
<div>
<button (click)="nochange()">NO CHANGE</button>
<input [(ngModel)]="name">
<button (click)="change('x')">CHANGE x</button>
<button (click)="change('y')">CHANGE y</button>
<button (click)="changeref()">CHANGE REF</button>
</div>
</article>
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './test.component.html',
styleUrls: [ './test.component.css' ]
})
export class AppComponent {
name = 'Angular';
obj:any;
constructor(){
this.obj = {x:'x', y:'y'}
}
doSomething(x, where) {
console.log("SOMTHING", x, where);
//DO SOMETHING WITH X
//this.name = "CIAO";
return x;
}
doParams(...args) {
console.warn("PARAMS", ...args);
return JSON.stringify(args);
}
nochange() {
console.log("NO CHANGE");
}
change(fld: string) {
console.log("CHANGE",fld);
this.obj[fld] = new Date();
}
changeref() {
this.obj = {x:'1', y:'2'}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment