Exploring Chrome's WebUSB Functionality with AngularJS

Recently, I encountered a challenge while utilizing WebUSB APIs for Chrome through AngularJS. This particular project involves accessing an esc/pos thermal printer for the purpose of printing invoices.

In typical 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)
            }
        });
    };

However, while experimenting with the Angular script, a DOMException arose, displaying an error message:

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

This requirement is set by the WebUSB's requestDevice function, which mandates a user-initiated action like a button click or mouse hover.

The first example functions well because the user explicitly clicks the button to trigger the function.

In the second example, a similar scenario unfolds. I even opted for a native event listener instead of ng-click to see if that resolves the issue, but unfortunately, that didn't work either.

Could someone provide assistance? What seems to be the issue with AngularJS in this context?

Answer №1

While the first example may be uncertain, it is important to note the significance of awaiting the promise returned by getDevices() before calling requestDevice() in the second example. This ensures that the async function proceeds only after the promise is resolved, eliminating the need for a user gesture in your code.

It is advisable to call getDevices() once during page load rather than on every click event. In order to detect a connected device after loading the page, consider adding an event listener with

navigator.usb.addEventListener('connect', ...)
.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The Art of Validating Forms in Vue.js

Currently I am in the process of developing a form with validation using Vue, however, I've run into some errors that are showing up as not defined even though they are currently defined. HTML <form class="add-comment custom-form" @submit="checkF ...

jQuery UI Slider is malfunctioning (code example included)

I've implemented a jQuery UI slider on my website, and it's functioning quite well. You can check out the slider HERE. However, I've noticed that when I click on 'back to the top', the page smoothly scrolls up. But when I use the ...

React Error: Invalid Element Type with Named Exports

I've been diving into the world of React hooks and functions, working on three different files. First, there's one that establishes a context called SummaryContext. The second file contains a class component that consumes this context named WikiS ...

What are some ways to integrate the features of ctype.h into JavaScript?

How can glibc's ctype.h be effectively translated into JavaScript? While I believe it is possible, I am struggling to locate the tables and bitshifting operations used in the C source code. What are the best techniques to employ in this situation? isa ...

Utilizing dynamic routes and incorporating additional search parameters within the URL structure in NextJS has never

Is there a way to use router.push(url); to redirect a user with a URL structure like this: [:lang]/something/[...dynamicRouteParams]?searchParam=true. The problem I'm facing is that the user ends up being redirected to a page with a URL structure lik ...

Discovering the status of a wrapped component using Jest

const wrapper = mount( <ContextProvider> <FreeformEquationQuestionPractice question={question} /> </ContextProvider> ) console.log('freeform state: ', wrapper.childAt(0).instance().state) FreeformEquationQues ...

Navigating through each segment

I'm currently working on a website with sections that are set to be 100% height of the window, but at least 800px tall. My goal is to implement a smooth scrolling functionality where one scroll moves the view from section to section. However, if the ...

Clicking on the (x) button element will eliminate the DOM node from a list

https://i.stack.imgur.com/GxVYF.png A value is being dynamically added to my page, and here is the code snippet: function favJobs(data){ number_of_jobs_applied = data.total_bookmarked; $('.bookmark-title').append(number_of_jobs_applied, " ...

Create a stylish frame for designated rows within a table

Col1 Col2 Col3 Col4 Col5 Col6 Row11 Row12 Row13 Row14 Row15 Row16 Row21 Row22 Row23 Row24 Row25 Row26 Row31 Row32 Row33 Row34 Row35 Row36 Looking for a way to add a border around rows with matching values in the first column, or around a specif ...

The post processing effect in Three.js does not support FXAA when SSAO is activated

I am having trouble getting SSAO and FXAA effects to work together in this simple test scene. Enabling SSAO works fine, but when I also enable FXAA, the render turns black. In the provided fiddle, if you uncomment composer.addPass(FXAA_effect); you will s ...

What is the reason for node-sass being rebuilt after upgrading from npm6 to npm7?

My application utilizes sass opposed to node-sass. Within my package-lock.json file, there is no mention of node-sass. I have been successfully using npm 6 for years without any issues. However, upon attempting to run npm install with npm 7, I encounter ...

Vue.js behaving abnormally due to certain circumstances

Currently, I am working on a vue application where I encountered some errors related to script execution on certain websites. By implementing the following code snippet, the issue is resolved: if ( window.location.href === 'chrome-extension:// ...

AWS Lambda, where the billing time exceeds the actual processing time

While working on my Lambda function in Node.js, I noticed a significant difference in the time measured from the start to the end of the function compared to the billed duration provided by Lambda. The function itself takes around 1400 milliseconds to exec ...

Add AngularJS to an AJAX call when the user clicks on it

I'm currently exploring the SoundCloud API and looking to implement a feature where users can add a song to the page by clicking on it from the search results. I've decided to utilize Plangular, which you can find more information about here. How ...

Store text in a table format in your local storage

I need help figuring out how to save product and price information to local storage when an "add to cart" button is pressed. Can someone provide guidance on how to do this? Here is the code I currently have: body> <!-- Header--> ...

Improving the Speed of ASP.NET TreeView

How can we optimize performance when using the TreeView component? When I say optimize performance, I am referring to reducing the number of client-server trips, such as postbacks. Does this imply that the majority of the business logic will need to be i ...

Having trouble setting the InnerHTML property of Null on my Ionic app, what could be the issue?

I'm working on a code to display the remaining time for generating a random code in the DOM. var count = setInterval(function () { var date = new Date(); var currentSecond = date.getSeconds(); ...

Leverage the power of AngularJS to send a PUT request to your Laravel

I am encountering an issue while attempting to send a put request using AngularJS in conjunction with Laravel. Upon sending the request, I am receiving the following error message: TypeError: Cannot set property '_method' of undefined ...

Is $scope.$emit ineffective within a callback function?

I am working on an authentication code and I need to call an event after receiving some data. However, I am facing an issue where "$scope.$emit" is not working in the callback of "User.me()" and I don't understand why. Can anyone clarify this for me? ...

Retrieve the value of a tag attribute while the tab is in the active state

Is there a way to extract the value from a specific tag when it is set as active? The tag in question looks like this: <li class="top-tab" role="tab" tabindex="0" aria-selected="true" aria-expanded="true"> TITLE OF SECTION </li> I am interes ...