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?