QuaggaJS in Angular 2 breaks Template Binding
See original GitHub issueI’m trying to pull QuaggaJS into an Angular 2 project and hit a UI snag. I was successful in implementing the livestream code, and am able to detect barcodes along with displaying the generated locator boxes on the image based on the data in result.
What I have found is an issue where QuaggaJS seems to interferes with Angular 2 template binding. After registering an arrow function as my callback to preserve this
I attempt to assign result.codeResult.code
to a variable in my AppComponent
class this.lastResult
. This assignment goes fine and dandy, as I can log this.lastResult
to the console and see the scanned info. What goes wrong is that after assigning the variable Angular 2 doesn’t update the displayed value. Setting the value using a generic control (E.g. button, checkbox, click handler) works as expected.
I get similar results using the constructor, the ngOnInit hook and the ngAfterViewInit hook. There’s a very finite amount of places to instantiate Quagga in the Angular lifecycle and with these three out none are considered the “right way” to do things.
Reproduction repo is available at https://github.com/gelliott181/ng2-quagga-issue To run:
- Clone the repo
- Run
npm install
to install the project (This project uses the Angular CLI) - Run
node_modules\.bin\ng s -h 0.0.0.0
to start a dev server on all interfaces - Browse to your dev server running on port 4200 using a device capable of running Quagga livestream code (I’ve used an Asus ZenPad 8 with Firefox Mobile)
Issue Analytics
- State:
- Created 7 years ago
- Comments:5
Top GitHub Comments
Fix found! It comes down to TypeScript being very picky about how things are passed around. Previously I’d registered callbacks using
Quagga.onProcessed(this.onProcessed);
which causes this issue, and before that I’d used an anonymous arrow function.To fix this I tried arrows again, but I replaced my anonymous function with
Quagga.onProcessed((result) => this.onProcessed(result));
. This resulted in no scope issues. I do have to note that change detection still won’t catch this update so I have to callChangeDetectorRef.detectChanges()
to update the template.I’ve pushed the working component to the reproduction repo under the
fix
branch.Here’s an interesting behavior: I added a forced check of the component tree for change detection by injecting
private ref: ChangeDetectorRef
and callingthis.ref.detectChanges();
in myQuagga.onDetected()
callback.My callback reports
this.ref
as being undefined even though they should exist in the same scope and zone already. This occurs with an injectedprivate ref: ApplicationRef
and a call tothis.ref.tick()
also.I logged my
this
again and it seems my scope isn’t preserved as well as I thought it was. Now to dive through the call stack to see where I lose it.