QZ giving errors on angular install and websocket not found - service

I am trying to get my angular webapp working with a star sp 700 receipt printer and am trying to integrate qz-tray into my software for that reason. I am getting an error when trying to install #types/qz-tray which is displayed below. Also I get an error
unresolved variable websocket
on the line 23 and
unresolved variable api
on line 16.
Can someone please tell me how to fix this and if there is a better way of printing to either this or another receipt printer through angular?
import { Injectable } from '#angular/core';
import { from as fromPromise, Observable, throwError } from 'rxjs';
import { HttpErrorResponse } from '#angular/common/http';
import { catchError, map } from 'rxjs/operators';
import * as qz from 'qz-tray';
import { sha256 } from 'js-sha256';
#Injectable({
providedIn: 'root'
})
export class PrinterService {
//npm install qz-tray js-sha256 rsvp --save
constructor() {
qz.api.setSha256Type(data => sha256(data));
qz.api.setPromiseType(resolver => new Promise(resolver));
}
// Get the list of printers connected
getPrinters(): Observable<string[]> {
console.log('+++++++++PrinterService+++++');
return fromPromise(
qz.websocket.connect().then(() => qz.printers.find())
)
map((printers: string[]) => printers)
, catchError(this.errorHandler);
}
// Get the SPECIFIC connected printer
getPrinter(printerName: string): Observable<string> {
return fromPromise(
qz.websocket.connect()
.then(() => qz.printers.find(printerName))
)
map((printer: string) => printer)
, catchError(this.errorHandler);
}
// Print data to chosen printer
printData(printer: string, data: any): Observable<any> {
const config = qz.configs.create(printer);
return fromPromise(qz.print(config, data))
map((anything: any) => anything)
, catchError(this.errorHandler);
}
private errorHandler(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
console.log(error.error);
console.log('An error occurred:', error.status);
return throwError(error.error);
} else {
console.log('An error occurred:', error.status);
console.log(error.error);
return throwError(error.error);
}
};
}

unresolved variable websocket
unresolved variable api
These are both signs that qz-tray.js did not load properly.
The objects qz.api and qz.websocket are both part of the qz namespace. If they're not available, then qz was never imported properly.
Here's a working example of QZ Tray running in Angular:
https://stackblitz.com/edit/angular-3h4cnv
The import line appears to be correct and matches that of the QZ Tray angular quickstart guide.
The import * as qz should be valid according to TypeScript guidelines on exporting the default export of a module however you can safely convert it to import { default as qz } from "qz-tray";
As a troubleshooting step, you can call:
console.log(qz);
If loaded properly, it should show something like this:
Another troubleshooting technique would be to remove and reinstall qz-tray using your preferred package manager npm uninstall qz-tray; npm install qz-tray, etc.

Related

SvelteKit console error "window is not defined" when i import library

I would like to import apexChart library which using "window" property, and i get error in console.
[vite] Error when evaluating SSR module /src/routes/prehled.svelte:
ReferenceError: window is not defined
I tried use a apexCharts after mount, but the error did not disappear.
<script>
import ApexCharts from 'apexcharts'
import { onMount } from 'svelte'
const myOptions = {...myOptions}
onMount(() => {
const chart = new ApexCharts(document.querySelector('[data-chart="profit"]'), myOptions)
chart.render()
})
</script>
I tried import a apexCharts when i am sure that browser exist.
import { browser } from '$app/env'
if (browser) {
import ApexCharts from 'apexcharts'
}
But i got error "'import' and 'export' may only appear at the top level"
I tried disable ssr in svelte.config.js
import adapter from '#sveltejs/adapter-static';
const config = {
kit: {
adapter: adapter(),
prerender: {
enabled: false
},
ssr: false,
}
I tried to create a component in which I import apexChart library and I created a condition that uses this component only if a browser exists
{ #if browser }
<ProfitChart />
{ /if }
Nothing helped.
Does anyone know how to help me please?
The easiest way is to simply include apexcharts like a standalone library in your webpage like this:
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
And then simply use it in the onMount:
onMount(() => {
const chart = new ApexCharts(container, options)
chart.render()
})
You can add this line either in your app.html or include it where it's required with a <svelte:head> block.
An alternative way would be to dynamically import during onMount:
onMount(async () => {
const ApexCharts = (await import('apexcharts')).default
const chart = new ApexCharts(container, options)
chart.render()
})
As an extra: use bind:this instead of document.querySelector to get DOM elements, that would be the more 'svelte' way.
I have found the last option with the Vite plugin to work best with less code in the end but will lose intellisense in vscode and see import highlighted as error (temp workaround at end): https://kit.svelte.dev/faq#how-do-i-use-x-with-sveltekit-how-do-i-use-a-client-side-only-library-that-depends-on-document-or-window
Install vite plugin: npm i -D vite-plugin-iso-import
Add plugin to svelte.config.js:
kit: {
vite: {
plugins: [
isoImport(),
],
Add plugin to TypeScript config (if you use TS):
"compilerOptions": {
"plugins": [{ "name": "vite-plugin-iso-import" }],
Use as normal but note the "?client" on the import:
<script context="module">
import { chart } from 'svelte-apexcharts?client';
import { onMount } from 'svelte'
let myOptions = {...myOptions}
onMount(() => {
myOptions = {...updated options/data}
});
</script>
<div use:chart={myOptions} />
Debugging note:
To have import not highlighting as an error temporarily, just:
npm run dev, your project will compile fine, then test in browser to execute at least once.
remove ?client now, save and continue debugging as usual.
For all of you trying to import dynamically into a js or ts file, try the following:
Import your package during on mount in any svelte component.
onMount(async () => {
const Example = await import('#creator/examplePackage');
usePackageInJSOrTS(Example.default);
});
Use the imported package in your js/ts function. You need to pass the default value of the constructor.
export function usePackageInJsOrTs(NeededPackage) {
let neededPacakge = new NeededPackage();
}

Ionic 5 Capacitor FileTransfer

I'm running in the browser an ionic 5 APP using capacitor and I'm trying to use the file transfer functionality. I follow the documentation https://ionicframework.com/docs/native/file-transfer and configure my app using capacitor. Thus running:
npm install cordova-plugin-file-transfer
npm install #ionic-native/file-transfer
ionic cap sync
In my app.module, I registered the providers:
import { FileTransfer } from '#ionic-native/file-transfer/ngx';
import { File } from '#ionic-native/file/ngx';
...
providers: [
StatusBar,
SplashScreen,
...
FileTransfer,
File
],
Note that I also installed the native file package, so in total I have the following 4 new packages:
"#ionic-native/file": "^5.27.0",
"#ionic-native/file-transfer": "^5.27.0",
"cordova-plugin-file": "^6.0.2",
"cordova-plugin-file-transfer": "^1.7.1",
My code in the component is:
import { Input, Component } from '#angular/core';
import { FileTransfer, FileTransferObject } from '#ionic-native/file-transfer/ngx';
import { File } from '#ionic-native/file/ngx';
#Component({
selector: 'app-order-detail-order-card',
templateUrl: './order-detail-order-card.page.html'
})
export class OrderDetailOrderCardPage {
#Input() pdfUrl: string;
#Input() orderCardId: string;
constructor(private transfer: FileTransfer, private file: File) { }
public downloadFile(): void {
const fileTransfer: FileTransferObject = this.transfer.create();
fileTransfer.download(this.pdfUrl, this.file.applicationDirectory + `${orderCardId}.pdf`).then((entry) => {
console.log('download complete: ' + entry.toURL());
}, (error) => {
// handle error
});
}
}
When I run the app in the browser, I get the following warning and I'm not sure whether the file should donwload somewhere?
common.js:284 Native: tried calling SplashScreen.hide, but Cordova is not available. Make sure to include cordova.js or run in a device/simulator
Even if I don't get the file, I would be expecting to see the "download complete" message. It's not very clear to me as to whether I have to configure something else in my app to be able to run it locally or I have to use this functionality ONLY in either the emulator or the device itself.
What else needs to be configured to get this to work?
common.js:284 Native: tried calling SplashScreen.hide, but Cordova is not available. Make sure to include cordova.js or run in a device/simulator
this means that you are using the browser emulator which doesn't have any splashscreen, you can totally ignore that warning ( you won't get it using a simulator or a real device).
You should paste the html section of that page too, because probably the download doesn't start because an incomplete url and it doesn't proceed with the "then()"
maybe i'm wrong, but it can be possible.

Tensorflowjs in ionic

I tried to use tensorflowjs in ionic. After converting existing model from python then import from ionic it works only when i runs on my local server (http://localhost:8100/ionic-lab)
However, when i build the project for android
tf.loadModel method not working, it fails to load model from local folder ( ie. assets/model )
I already checked this link Tensorflow.js with react-native
, but it doesn't help. I guess, lots of hybrid mobile app frameworks are pretty much the same line. Any advice and suggestions will be greatly appreciated.
import {Component} from '#angular/core';
import {IonicPage, AlertController} from 'ionic-angular';
import {HttpClient} from "#angular/common/http";
import * as tf from "#tensorflow/tfjs";
#IonicPage()
#Component({
selector: 'page-tfpretrainedversion',
templateUrl: 'tfpretrainedversion.html',
})
export class TfpretrainedversionPage {
kerasTraindedModel: tf.Model;
KERAS_MODEL_JSON = 'assets/model/model.json';
constructor(private httpClient: HttpClient,
private alertCtrl: AlertController) {
this.loadPretrainedModel();
}
loadPretrainedModel() {
tf.loadModel(this.KERAS_MODEL_JSON)
.then((result) => {
this.kerasTraindedModel = result;
})
.catch((error)=>{
let prompt = this.alertCtrl.create({
title: 'Error',
subTitle: error,
buttons: ['OK']
});
prompt.present();
});
}
}
Here is an error message
Failed to fetch
And here is a project structure
Project structure
TensorflowJs loads the models via fetch(). fetch() does not support loading local-files. https://fetch.spec.whatwg.org/
My Workaround:
Use a polyfill (https://github.com/github/fetch) and replace the fetch.
window.fetch = fetchPolyfill;
Now, it's possible to load local files (file:///) like:
const modelUrl = './model.json'
const model = await tf.loadGraphModel(modelUrl);

Using mongodb-stitch library in Angular 4

Im been trying the MongoDB Stitch service in Angular, so far Im able to use the service. However, the only way I could connect to the service is by including the js library hosted in AWS on the html page.
There is a mongodb-stitch npm package available and there are sample pages on mongodb tutorial on how to use it. But this is a pure JS library (no TS support) and I have tried several ways (using require, installing typings of the lib (not available), using #types) to no avail.
Anyone tried this on Ng4? Would love to have the steps you did to use the 'mongodb-stitch' package the create a service.
The other answer suggests instantiating a new instance of StitchClient which is something that MongoDB have explicitly advised against in the Official API Documentation - and with reason, since there is a factory method available for that purpose. So, (after installing mongodb-stitch), the following code would help you get started in component.ts
import { Component, OnInit } from "#angular/core";
import { StitchClientFactory } from "mongodb-stitch";
let appId = 'authapp-****';
#Component({
selector: "app-mongo-auth",
templateUrl: "./mongo-auth.component.html",
styleUrls: ["./mongo-auth.component.css"]
})
export class MongoAuthComponent implements OnInit {
mClient;
ngOnInit() {
this.mClient = StitchClientFactory.create(appId);
}
And you can then use this for whatever purpose you want, such as for implementing sign-in with Google
gLogin(){
this.mClient.then(stitchClient => {
stitchClient.authenticate("google");
})
not sure whether the question is still relevant considering it was asked two months ago but anyway...
As you pointed out you can use
npm install --save mongodb-stitch
to install the package and since there is no TS binding you can declare the stitch library as any
For example:
declare var stitch: any;
export class MyService implements OnInit {
db;
client;
ngOnInit() {
this.client = new stitch.StitchClient('<check the stitch app page for proper value>');
this.db = this.client.service('mongodb', 'mongodb-atlas').db('<the db name goes here>');
this.client.login();
}
save() {
this.db.collection('<collection name>').insertOne({key : 'value'}).then(() => console.log("All done"));
}
}
the previous answers are functional, but i wanna share a example using a service injectable.
service.ts
import { Injectable } from '#angular/core';
import { Jsonp, URLSearchParams } from '#angular/http';
import { StitchClientFactory } from "mongodb-stitch";
import 'rxjs/add/operator/map';
#Injectable()
export class Service {
constructor(private jsonp: Jsonp) { }
client;
connect(){
this.client = new StitchClientFactory.create("App ID"); // Slitch apps > Clients > App ID
this.client.then(stitchClient => stitchClient.login())
.then((stitchClient) => console.log('logged in as: ' + stitchClient))
.catch(e => console.log('error: ', e));
}
all() {
this.connect();
return this.client.then(stitchClient => {
let db = stitchClient.service('mongodb', 'mongodb-atlas').db("database Name"); // Slitch apps > mongodb-atlas > Name database.Collection
let itemsCollection = db.collection('name collection'); // Slitch apps > mongodb-atlas > Name database.Collection
console.log(itemsCollection.find().execute());
return itemsCollection.find().execute();
})
.then(result => {return result})
.catch(e => console.log('error: ', e));
}
}
after make the previous file, you must create a module to receive the data, so:
module.ts
import { Component, OnInit, Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { StitchClientFactory } from "mongodb-stitch";
import { Service } from 'service'; // previous code
declare var stitch: any;
#Component({
template: '
<ul class="demo-list-icon mdl-list">
<li class="mdl-list__item" *ngFor="let item of data | async">
<span class="mdl-list__item-primary-content">
<i class="material-icons mdl-list__item-icon">{{propiedad.nombre}}</i>
</span>
</li>
</ul>
'
})
export class MainComponent implements OnInit {
data: Observable<[]>;
constructor(private Service: service) {
}
ngOnInit() {
this.propiedades = this.Service.all();
}
}
important, you don´t must forget to add service on module.ts intitial declarations.
mongodb Atlas
mongodb-stitch vía NPM
Documentation mongoDB Stitch.
Sure!

Angular2 HTTP - How to understand that the backend server is down

I am developing a front end which consumes JSON services provided by a server.
I happily use HTTP of Angular2 and I can catch errors via .catch() operator.
If I find a problem related to a specific service (e.g. the service is not defined by the server) the catch() operator receives a Response with status 404 and I can easily manage the situation.
On the other hand, if it is the server that is completely down, the catch() operator receives a Response with status code 200and no specific sign or text related to the cause of the problem (which is that the whole server is down).
On the console I see that angular (http.dev.js) writes a message net::ERR_CONNECTION_REFUSED but I do not know how to do something similar (i.e. understand what is happening and react appropriately) from within my code.
Any help would be appreciated.
If you would like to handle this event globally in your application I recommend using slightly modified Nicolas Henneaux's answer https://stackoverflow.com/a/37028266/1549135
Basically you can check for error.status === 0 which happens when the net::ERR_CONNECTION_REFUSED error occurs.
The complete module file:
import { Request, XHRBackend, BrowserXhr, ResponseOptions, XSRFStrategy, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
export class AuthenticationConnectionBackend extends XHRBackend {
constructor(_browserXhr: BrowserXhr, _baseResponseOptions: ResponseOptions, _xsrfStrategy: XSRFStrategy) {
super(_browserXhr, _baseResponseOptions, _xsrfStrategy);
}
createConnection(request: Request) {
let xhrConnection = super.createConnection(request);
xhrConnection.response = xhrConnection.response.catch((error: Response) => {
if (error.status === 0){
console.log("Server is down...")
}
...
return Observable.throw(error);
});
return xhrConnection;
}
}
Module file:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { HttpModule, XHRBackend } from '#angular/http';
import { AppComponent } from './app.component';
import { AuthenticationConnectionBackend } from './authenticated-connection.backend';
#NgModule({
bootstrap: [AppComponent],
declarations: [
AppComponent,
],
entryComponents: [AppComponent],
imports: [
BrowserModule,
CommonModule,
HttpModule,
],
providers: [
{ provide: XHRBackend, useClass: AuthenticationConnectionBackend },
],
})
export class AppModule {
}
I have the same problem while using angular2.0.0-beta.15
It seems like this is a bug. You get http status 200 and this is not correct:
https://github.com/angular/http/issues/54
Well i have faced something similar before. I was trying to make a logging Service and a Error handling which tells the user if error happened with some requests to the server or if the whole server is down.
I used HTTP Interceptor to catch the responses here is the code:
export class HttpErrorHandlingInterceptor implements HttpInterceptor {
constructor(private logService: LogService,
private layoutStateService: LayoutStateService){}
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (req.url) {
return next.handle(req).pipe(
map((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
return event;
}
}),catchError(err => {
if(!err.status){
this.layoutStateService.dispatchServerDown();
}else{
this.layoutStateService.dispatchAddServerError(err);
this.logService.logError(err);
}
throw err;
})
);
}
}
}
Now you can specify what should happen when Server is down according to your application.
Hope that helps.