Rob Rob - 1 month ago 11
Javascript Question

Access Angular2 app through window loses scope of "this"

I have an Angular2 app that I have exposed certain methods to code running outside of ng2. The problem is that

this
is not the same when called outside of ng2 vs inside.

https://plnkr.co/edit/KZeH1ArvuMTmsBCFjNnY
(watch the console to see whats happening)

In my app component it sets the name to "Angular2" on load. I have the
doSomething
method that does a simple
this.name = "modified angular2 app
. When I call this through
window.myVar.doSomething()
the scope of
this
is not my class, its the object I exposed. How can I access the
name
. I have tried
self = this
in the constructor and doing
self.name =
which works, but when I bundle and minify for production it fails.

@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
</div>
`,
})
export class App {
name:string;

constructor() {
this.name = 'Angular2'
}

doSomething(){
this.name = "modified angular2 app"
}

ngOnInit() {

window.myVar = {doSomething:this.doSomething}

}

}


In my
index.html
I have added a snippet to call my
doSomething
method.

<body>
<my-app>
loading...
</my-app>
<script>
function checkReady() {
if (window.myVar) {
console.log("Ready")
console.log(myVar)
myVar.doSomething();
} else {
setTimeout(function() {
console.log("Not ready")
checkReady()
}, 500)
}
}
checkReady()
</script>
</body>

Answer

TypeScript has the fat-arrow syntax, you can use that to automatically bind this to the class instance:

export class App
{
  //...
  doSomething = () => {
    this.name = "modified angular2 app" 
  }
  //...
}

Be aware of that this syntax leads to the function doSomething is no longer a part of the prototype of App.

More info about this in typescript/javascript here with pros and cons for different strategies.