Citizen Citizen - 2 months ago 6
Javascript Question

Callback isolated from component's properties

I am new with TypeScript and Angular 2.

I have a strange problem with Cordova Camera Plugin : when I take a photo, it seems callbacks are isolated from the rest of the component !

Here the code :

result.component.ts

import {Component, OnInit} from "@angular/core";

@Component({
moduleId: module.id,
selector: 'app-result',
templateUrl: 'result.component.html'
})
export class ResultComponent implements OnInit {
pictureSource;
destinationType;
status = 0; //VALUE I WANT TO PRINT

constructor() {
this.pictureSource = navigator.camera.PictureSourceType;
this.destinationType = navigator.camera.DestinationType;
}

ngOnInit(): void {

}

test() {
console.log(this.status); //VALUE I PRINT
}

capturePicture() {
let cameraOptions = {
quality: 100,
destinationType: this.destinationType.FILE_URI
};
navigator.camera.getPicture(this.onCaptureSuccess, this.onCaptureFail, cameraOptions);
}

onCaptureSuccess(fileURI: string): void {
console.log(this.status); //THROW ERROR
}

onCaptureFail(error: string): void {
console.log('error', error);
}
}


result.component.html

<div>
<h1>Photo</h1>

<button (click)="capturePicture()">PHOTO</button>
<button (click)="test()">TEST</button>
</div>


Console output :
Console output

When I click on
TEST button
(8 times in this screenshot), I've got console.log whose works.
Then, when I click on
PHOTO button
, take the picture, and come back, I've got
Cannot read property 'status' of null

Then, I click 4 times on
TEST button
and status value appears....

It seems
navigator.camera.getPicture
's callbacks are isolated from the rest of the component, how can we explain that ?

Answer

I never used Angular or Cordova, but it looks like a simple loss of this context. The click handler from Angular does respect the components context. But in the line...

navigator.camera.getPicture(this.onCaptureSuccess, this.onCaptureFail, cameraOptions);

...you just hand over a reference to a function and getPicture cannot know your context. One way to solve this, is to bind on this:

navigator.camera.getPicture(this.onCaptureSuccess.bind(this), this.onCaptureFail, cameraOptions);

Or use an arrow function, or buffer this yourself with a closure, or...

Comments