0

I am having an issue while using WebUSB APIs for chrome through angularJS. This is a project where I need to access an esc/pos thermal printer for printing invoice.

In normal javascript:

HTML:

<button id="connect">Connect</button>

Javascript:

document.addEventListener('DOMContentLoaded', async () => {
    try{
        let devices = await navigator.usb.getDevices({
            filters: [{
                vendorId: VENDOR_ID,
                productId: PRODUCT_ID
            }]
        });
        let button = document.getElementById('connect');

        button.addEventListener('click', async () => {
            if (devices.length === 0) {

                var device;
                let devices = [];

                try {
                    device = await navigator.usb.requestDevice({
                        filters: [{
                            vendorId: VENDOR_ID,
                            productId: PRODUCT_ID
                        }]
                    });
                }
                catch (error) {
                    console.log(error)
                }
            }
            else {
                device = devices[0];
            }
            console.log('open');
            await device.open();
            console.log('opened:', device);
            await device.selectConfiguration(1); // Select configuration #1 for the device.
            await device.claimInterface(0); // Request exclusive control over interface #0.
            console.log(await device.transferOut(2,buffer));
        })

    }
    catch (error) {
        console.log(error)
    }

in angularjs: HTML:

<button class="btn btn-warning" ng-init="newinvscopetest.bindPrint()" id="print">Print</button>

controller:

newinvscopetest.bindPrint = function (){
        let button = document.getElementById('print');

        button.addEventListener('click', async () => {
            let device;
            let devices = [];
            const VENDOR_ID = 0x0FE6;
            const PRODUCT_ID = 0x811E;
            try {
                devices = await navigator.usb.getDevices({
                    filters: [{
                        vendorId: VENDOR_ID,
                        productId: PRODUCT_ID
                    }]
                });
                if (devices.length === 0) {
                    try {
                        device = await navigator.usb.requestDevice({
                            filters: [{
                                vendorId: VENDOR_ID,
                                productId: PRODUCT_ID
                            }]
                        });
                    }
                    catch (error) {
                        console.log(error)
                    }
                }
                else {
                    device = devices[0];
                }
                console.log('open');
                await device.open();
                console.log('opened:', device);
                await device.selectConfiguration(1); // Select configuration #1 for the device.
                await device.claimInterface(0); // Request exclusive control over interface #0.
                let buffer = newinvscopetest.getPrintData();
                console.log(await device.transferOut(2,buffer));
            }
            catch (error) {
                console.log(error)
            }
        });
    };

While trying with the angular script a DOMException is throwing an error :

Must be handling a user gesture to show a permission request.

This is required by web usb's requestDevice function, which is supposed to be a user button click or mouse hover.

And this is working fine in the first example because the user is clicking the button to trigger the function.

In the 2nd example, the same thing is happening. I even avoided ng-click to have native event listener to try if that work. But no luck with that too.

Can anyone help me? What is going wrong in angularJS?

Sudip dey
  • 7
  • 9

1 Answers1

0

I'm not sure about the first example but in the second example, before calling requestDevice() you await the promise returned by getDevices(). This means that the rest of your async function is called after this promise is resolved and your code no longer has a user gesture.

Instead of calling getDevices() on every click I recommend calling it only once on page load and using an event listener (added with navigator.usb.addEventListener('connect', ...)) to detect a device connected after the page load.

Reilly Grant
  • 5,590
  • 1
  • 13
  • 23
  • Thanks for the confirmation. I was thinking the same thing. I will test this soon. But tell me one thing. If I use ng-click instead of addEventListener for the button press, will it still be user gesture? – Sudip dey Apr 26 '18 at 18:48
  • It should be the same. If it isn't that sounds like a bug in Angular. – Reilly Grant Apr 27 '18 at 19:52