Ionic vue framework (CAPACITOR), QRCode Scanner Issue - vue.js

In my ionic vue.js project I using capacitor and I want to read QR Code from camera but there is no way I found on search about nothing for ionic vue.js especially. I tried more than I found this little thing 'https://www.npmjs.com/package/vue3-qrcode-reader'. With this little thing I can read QR Code from web and Android phones but iOS devices not work with that. I try capacitor-barcode-scanner to. If I try with capacitor-barcode-scanner Xcode give me error like 'you need to upgrade development target version' and upgrade to. Please tell me there is no way for build QR Code scanner app with IONIC - VUE WITH CAPACITOR? ;
Here is my errors with vue3-qrcode-reader
and here is my code which I use
<template>
<ion-page>
<ion-header class="ion-no-border" >
<ion-toolbar style="--background: var(--primary)">
<ion-buttons slot="start">
<ion-back-button text=""></ion-back-button>
</ion-buttons>
<ion-title style="color: white">Please Read Barcode</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<qr-stream #decode="onDecode" class="mb">
<div style="color: yellow;" class="frame"></div>
</qr-stream>
</ion-content>
<div style="background-color: var(--primary); width: 100%; position: fixed; bottom: 0; padding: 20px">
<p style="color: blue; text-align: center; color: white">Please Read Barcode On Paper</p>
</div>
</ion-page>
</template>
<script >
import { QrStream } from 'vue3-qr-reader';
import { Camera } from '#capacitor/camera';
import { defineComponent } from 'vue';
import {IonBackButton, IonButtons, IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from "#ionic/vue";
export default defineComponent({
name: 'barcode-read',
components: {
QrStream,
IonContent,
IonPage,
IonHeader,
IonTitle,
IonToolbar,
IonBackButton,
IonButtons,
},
created() {
Camera.requestPermissions();
},
methods: {
onDecode(data) {
console.log("Decoder = "+data);
this.$router.push('Welcome')
}
},
});
</script>

A workaround could be to take a picture and then parse it using a different package like this one: https://www.npmjs.com/package/qrcode-reader, but a real-time solution would be preferable.

Which iOS version are you using? iOS versions older than 14.2 do not allow using WebRTC in a webview.
You can try capacitor plugins like this: capacitor-plugin-dynamsoft-barcode-reader

Related

Rendering nested components

I am starting to learn VueJS by building a simple website.
Right now I have made three components:
Header
Navigation
Topbar
I want to render navigation and topbar inside header, so I can call the header component inside every page (I haven't found a way to make a "layout" or something, that every page uses).
Header.vue
<template>
<header id="topNav">
<topbar />
<navigation />
</header>
</template>
<script lang="ts">
import Vue from 'vue'
import navigation from '../navigation/navigation.vue'
import Topbar from '../topbar/topbar.vue'
export default Vue.extend({
components: { Topbar, navigation },
})
</script>
<style scoped>
#topNav {
background-color: #fff;
-webkit-box-shadow: 0 0 35px 0 rgb(154 161 171 / 15%);
box-shadow: 0 0 35px 0 rgb(154 161 171 / 15%);
position: fixed;
left: 0;
right: 0;
top: 0;
z-index: 1001;
padding: 0 12px;
}
</style>
Topbar
<template>
<div id="topBar">
<h2>this is the topbar</h2>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({})
</script>
<style scoped>
#topBar {
border-bottom: 1px solid #dee2e6;
height: 70px;
padding: 0 10px;
z-index: 100;
position: fixed;
left: 0;
right: 0;
}
</style>
And when I call it on for example my home page (index.vue) nothing renders.
<template>
<main>
<header />
<div id="page-content">
<h1>Home</h1>
</div>
</main>
</template>
<script lang="ts">
import Vue from 'vue'
import Header from '../components/header/header.vue'
export default Vue.extend({
name: 'Home',
components: { Header },
})
</script>
I've tried reading the documentation and search around, but haven't been able to figure out what I'm doing wrong.
Since the question is tagged with a Nuxt tag, I'll recommend looking into Nuxt layouts: https://nuxtjs.org/docs/concepts/views#layouts
There is a default named default that you could use by creating the file /layouts/default.vue and passing the components inside of it.
You can of course change that with a layout: 'yolo' if you want another 'yolo` layout.
Pro tip: you don't need to import the components yourself in Nuxt.
You have named your component header, which is a standard html element. Therefore the browser will probably just try to render a standard <header> element instead of your component.
Therefore it is advised to always use multi word component names. See docs here. You can use eslint in your code editor to help you spot these mistakes.
PS: if you are learning vue from the start, I would advise you to use the composition api with the script setup approach, as it makes things easier and provide the opportunity to write clearer code as components grow.

Font Awesome not rendering in Vue built Web Component

I have a Vue component that I'm compiling into a web component using the following build command:
npm run build -- --target wc --name projName src\components\server-config.vue
I'm missing something though in my Vue file cause the web component won't render the font awesome icons. Here is what it looks like when I, "npm run serve"
This is what it looks like after I compile it into a web component and open it in demo.html:
I see several issues:
Fonts are different
Missing Eye button for peeking the password
Checkbox box is missing (though if you mouse over it you still get a glow effect)
Eye icon is missing. (Just included as a test outside of Vuetify)
How can I properly include fonts into my component? Here is my current vue file:
<template>
<div style="text-align: center; font-family: sans-serif">
<v-text-field label="Password" class="mx-4" v-model="password" :type="showPass ? 'text' : 'password'" #click:append="showPass = !showPass" :append-icon="showPass ? 'far fa-eye' : 'far fa-eye-slash'"></v-text-field>
<v-checkbox class="mx-4" v-model="useIntegratedAuthentication" label="Use Integrated Authentication" ></v-checkbox>
<div>
<i class="far fa-eye"></i>
<span>My eye here</span>
</div>
</div>
</template>
<style scoped>
#import '../../node_modules/vuetify/dist/vuetify.min.css';
#import 'https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900';
#import 'https://cdn.jsdelivr.net/npm/#mdi/font#latest/css/materialdesignicons.min.css';
</style>
<script src="https://kit.fontawesome.com/XXXXXXXXX.js" crossorigin="anonymous"></script>
<script lang="ts">
import { VTextField, VCheckbox } from 'vuetify/lib';
import vuetify from '#/plugins/vuetify';
import Vue from 'vue';
export default Vue.extend({
vuetify,
components: {
VTextField, VCheckbox
},
data() {
return {
showPass: false,
password: '',
useIntegratedAuthentication: false
};
}
})
</script>
Figured out a workable solution. You need to load the font-faces inside a script tag after the component is mounted:
mounted() {
const css = `
#font-face {
font-family: 'Font Awesome 5 Free';
font-style: normal;
font-weight: 400;
font-display: block;
src: url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-brands-400.eot);
src: url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-brands-400.woff2) format("woff2"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-brands-400.woff) format("woff"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-brands-400.ttf) format("truetype"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-brands-400.svg#fontawesome) format("svg")
}
#font-face {
font-family: 'Font Awesome 5 Free';
font-style: normal;
font-weight: 400;
font-display: block;
src: url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-regular-400.eot);
src: url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-regular-400.woff2) format("woff2"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-regular-400.woff) format("woff"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-regular-400.ttf) format("truetype"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-regular-400.svg#fontawesome) format("svg")
}
#font-face {
font-family: 'Font Awesome 5 Free';
font-style: normal;
font-weight: 900;
font-display: block;
src: url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-solid-900.eot);
src: url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-solid-900.woff2) format("woff2"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-solid-900.woff) format("woff"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-solid-900.ttf) format("truetype"), url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/webfonts/fa-solid-900.svg#fontawesome) format("svg")
}`;
// if our style is already injected we do not need to inject it a second time
if (!document.getElementById('myCustomInjectedStyle')) {
const head = document.head || document.getElementsByTagName('head')[0];
const style = document.createElement('style');
style.id = 'myCustomInjectedStyle';
style.type = 'text/css';
style.innerText = css;
head.appendChild(style);
}
},
I never got material designs to work for the checkbox so I updated my vuetify.ts file to always use font awesome.
import Vue from 'vue'
import Vuetify from 'vuetify/lib/framework'
Vue.use(Vuetify)
export default new Vuetify({
icons: {
iconfont: 'fa'
}
})
Use font awesome globally
Add in yuor project/public/index.html head tag
<link rel="stylesheet" ref="https://use.fontawesome.com/releases/v5.6.1/css/all.css" integrity="sha384-gfdkjb5BdAXd+lj+gudLWI+BXq4IuLW5IT+brZEZsLFm++aCMlF1V92rMkPaX4PP" crossorigin="anonymous">
And use the tags from their site in your component. like <i class="fab fa-adn"></i>

Rendering a vue2leaflet map in jsfiddle via CDN

I am trying to render a Leaflet map using Vue2Leaflet in a jsfiddle so I can get help with a specific problem but I can't even get it to render properly in the trivial case. I have already looked up how to load libraries via CDN in jsfiddle and a far as I can tell, I am doing it right. There are also no errors in the console. But the map will not render.
This is the jsfiddle: https://jsfiddle.net/iboates/bywzgf1q/3/
Vue2Leaflet also requires the vue-client-only library. I have it working in my local codebase but maybe it has something to do with why it isn't working in jsfiddle. I am also loading this library via a CDN.
I've also looked at other jsfiddles using Vue with custom libraries loaded via CDN and I don't see what is being done differently.
Apparently StackOverflow requires that a jsfiddle link requires code in the post as well, which is a bit weird to me since the code is literally contained in a link which can also execute it, but here it goes:
HTML:
<div id="app">
<client-only>
<l-map id="map" ref="map">
<l-tile-layer
:attribution="'x'"
:url="'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'"
/>
<!-- <l-geo-json
:geojson="geojsonData"
/> -->
</l-map>
</client-only>
</div>
JS:
import { LMap, LTileLayer } from "./vue2-leaflet";
new Vue({
el: "#app",
components: {
LMap,
LTileLayer,
ClientOnly
},
data: {
geojsonData: {
type: "FeatureCollection",
features: []
}
},
mounted() {
}
})
CSS
#app {
background-color: black;
height: 500px;
width: 500px;
}
#map {
height: 500px;
width: 500px;
}
There are multiple errors in your fiddle.
First of all, Vue is not installed. In addition, you try to import Vue-Leaflet like in a Webpack / Rollup build system and not the way you can use it from a CDN.
To begin with, install your CDN (Vue, Leaflet CSS, Leaflet js, Vue-Leaflet):
https://cdn.jsdelivr.net/npm/vue#2.6.12/dist/vue.js
https://unpkg.com/leaflet#1.7.1/dist/leaflet.css
https://unpkg.com/leaflet#1.7.1/dist/leaflet.js
https://unpkg.com/vue2-leaflet#2.6.0/dist/vue2-leaflet.min.js
Then, add your components the CDN-way (check official documentation: https://vue2-leaflet.netlify.app/quickstart/#if-imported-by-cdn
):
components: {
'l-map': window.Vue2Leaflet.LMap,
'l-tile-layer': window.Vue2Leaflet.LTileLayer
}
Check working fiddle: https://jsfiddle.net/scpta4jq/1/

L-map, not displayed correctly, vue2leaflet in a framework7 popup

i have the next popup
<f7-popup class="demo-popup" :opened="popupDetalle" #popup:closed="popupDetalle = false">
<f7-page>
<f7-navbar title="Editar servicio">
<f7-nav-right>
<f7-link popup-close>Cerrar</f7-link>
</f7-nav-right>
</f7-navbar>
<div id="app">
<l-map ref="mymap" :zoom="zoom" :center="center">
<l-tile-layer :url="url" :attribution="attribution">
</l-tile-layer>
<l-marker :lat-lng="marker.position"></l-marker>
</l-map>
</div>
</f7-page>
</f7-popup>
in my script:
<script>
import 'leaflet/dist/leaflet.css';
import { LMap, LTileLayer, LMarker, LPopup } from "vue2-leaflet";
export default {
components:{
LMap,
LTileLayer,
LMarker,
LPopup
}
}
</script>
and css:
<style scoped>
.appMap {
width: 100%;
height: 400px;
}
</style>
and main.js:
import L from 'leaflet'
import { Icon } from 'leaflet'
import 'leaflet/dist/leaflet.css'
delete L.Icon.Default.prototype._getIconUrl
L.Icon.Default.mergeOptions({
iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
iconUrl: require('leaflet/dist/images/marker-icon.png'),
shadowUrl: require('leaflet/dist/images/marker-shadow.png')
})
But visually it looks like this:
Basically I am guiding with the documentation, the css and its components are imported, guide https://korigan.github.io/Vue2Leaflet/#/quickstart.md
I suspect you'll find that Leaflet loads the map tiles correctly if you resize the browser window after the map is showing.
When the map is first created it'll be hidden so Leaflet won't know how big it is. You need to give it a kick once the popup is shown. Leaflet itself can watch for a browser window resize but it doesn't know anything about your popup.
You've already got ref="mymap" on the <l-map> so it should just be a matter of invalidating the size using:
this.$refs.map.mapObject.invalidateSize()
You'll need to find a suitable place to make that call, after the popup is showing. Timing is critical, if you call it too soon then the size will still be wrong and it won't help.
Initially you may want to add a button and put the invalidateSize call inside its click handler. Obviously this isn't an acceptable solution but it will allow you to see the effect of calling invalidateSize, confirming that this does fix the problem with the tiles not loading.

VueJS + Nuxtjs Unexpected Token 'export'

So i have this code as my index page and It was working, but a couple minutes later it just stopped.
the error is:
SyntaxError
Unexpected token export
Within the script section, If i remove my import then the error will go away, but I need to import it and use it. It was working with the package being imported, but I have looked this code up and down I have no idea what the heck is going on.
Anyone have any suggestions? Am I dumb and have missed something so simple?
<template>
<section class='container'>
<img class='my-4' src="~/assets/images/carousel/1.png" alt="card" />
<div class='text-center mx-auto my-4'>
<button> Send a card </button>
<p class='subtle my-4'> Or </p>
<button class='btn-blue'> Open a card </button>
</div>
<div id="qrcode"></div>
</section>
</template>
<script>
import qrcode from 'qrcode-generator-es6'; <<<<<<<<< SYNTAX ERROR AROUND HERE
export default{
data : function(){
return {};
},
methods : {
},
mounted : function(){
const qr = new qrcode(0, 'M');
qr.addData('https://app.voxicard.com/?v=vx-9FEFCA66-F592-4FF5-97B8-93B2FD78666D');
qr.make();
document.getElementById('qrcode').innerHTML = qr.createSvgTag({
margin : 0,
cellColor : function(){
return "#48658B";
},
});
},
};
</script>
<style>
#qrcode {
width: 200px;
height: 200px;
background-color: red;
}
img {
display: block;
max-height: 500px;
text-align: center;
margin: auto;
}
button {
font-size: 125%;
}
</style>
In your build property in nuxt.config.js you'll need to add a transpile block that targets this library:
build: {
transpile: [
'qrcode-generator-es6'
]
}
This is due to the fact that nuxt expects libraries to export as CJS modules and not ES6 modules.
In nuxt.config.js replace export default { on module.exports = {