Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QuaggaJS in Angular 2 breaks Template Binding #146

Closed
eight-molecules opened this issue Nov 29, 2016 · 5 comments
Closed

QuaggaJS in Angular 2 breaks Template Binding #146

eight-molecules opened this issue Nov 29, 2016 · 5 comments

Comments

@eight-molecules
Copy link

eight-molecules commented Nov 29, 2016

I'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:

  1. Clone the repo
  2. Run npm install to install the project (This project uses the Angular CLI)
  3. Run node_modules\.bin\ng s -h 0.0.0.0 to start a dev server on all interfaces
  4. 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)
@eight-molecules
Copy link
Author

eight-molecules commented Nov 29, 2016

I did a little more investigation to see what's going on, and Angular's change detection code isn't triggered at all when this.lastResult is modified, even though logging the entire this object shows the lastResult property has in fact been updated and is referencing the AppComponent. This also seems like a failure in Angular more than Quagga interference now.

@matthewma7
Copy link

@gelliott181, I believe this issue is related to WebWorker. Your problem should go away immediately once you set numOfWorkers to 0, which is the workaround I chose. You could also call angular zone to forcefully rerender, but this method doesn't feel clean to me.

@eight-molecules
Copy link
Author

eight-molecules commented Nov 30, 2016

WebWorkers aren't an issue. I did try numOfWorkers: 0, and still have the same issue. I also know I can work with the result just fine using numOfWorkers: 4 (It assigns the variable and I can both read and manipulate it), but Angular's change detection never sees the change, so the templated display never updates to reflect the new value.

@eight-molecules
Copy link
Author

eight-molecules commented Nov 30, 2016

Here's an interesting behavior: I added a forced check of the component tree for change detection by injecting private ref: ChangeDetectorRef and calling this.ref.detectChanges(); in my Quagga.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 injected private ref: ApplicationRef and a call to this.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.

@eight-molecules
Copy link
Author

eight-molecules commented Nov 30, 2016

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 call ChangeDetectorRef.detectChanges() to update the template.

I've pushed the working component to the reproduction repo under the fix branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants