For a university project I have to implement an Ionic App using Ionic 4.
In the app you can scan a QR-Code, which provides data about a specific Street Art from a JSON File and displays it in the camera preview using the cordova plugin. This works fine.
I am now trying to set a boolean in the JSON-File to true, after scanning the QR-Code, in order to show a list with only the data of the scanned QR-Codes.
I have tried to use the Cordova File-Plugin, but I just do not manage to get it to work.
setJson(fileName, object) {
this.file.writeFile(this.dataDirectory,this.fileName,
JSON.stringify(this.object), {append: true, replace: false});
}
At the moment I am getting this error: EncodingError: A URI supplied to the API was malformed, or the resulting Data URL has exceeded the URL length limitations for Data URLs.
ar.page.ts:
import { Plugins } from '@capacitor/core';
import { Component, OnInit, Inject, ViewEncapsulation } from
'@angular/core';
import { BarcodeScanner } from '@ionic-native/barcode-scanner/ngx';
import { JsonDataService } from '../../json-data.service';
import { DOCUMENT } from '@angular/common';
import { Toast } from '@ionic-native/toast/ngx';
import { Router, NavigationExtras } from '@angular/router';
import { NavController, ModalController } from '@ionic/angular';
import { File } from '@ionic-native/file/ngx';
import {
CameraPreview,
CameraPreviewOptions
} from '@ionic-native/camera-preview/ngx';
import { Platform } from '@ionic/angular';
import { ModalPagePage } from '../modal-page/modal-page.page';
const { Browser } = Plugins;
@Component({
selector: 'app-ar',
templateUrl: './ar.page.html',
styleUrls: ['./ar.page.scss'],
encapsulation: ViewEncapsulation.None
})
export class ArPage implements OnInit {
datenData = [];
selectedProduct: any;
productFound = false;
fileName = 'data.json';
dataDirectory = this.file.applicationDirectory + 'assets/data/';
object = {boolean: true};
constructor(
private barcodeScanner: BarcodeScanner,
private datenService: JsonDataService,
private toast: Toast,
private router: Router,
public modalController: ModalController,
public navCtrl: NavController,
private cameraPreview: CameraPreview,
private platform: Platform,
public file: File,
@Inject(DOCUMENT) private _document
) {
fetch('../../../assets/data/data.json')
.then(res => res.json())
.then(data => {
this.datenData = data.jsondata;
this.datenService.setJsondata(this.datenData);
console.log(data);
});
}
ngOnInit() {
this.qrscan();
}
qrscan() {
this.datenData = this.datenService.getJsondata();
this.selectedProduct = {};
this.barcodeScanner.scan().then(
barcodeData => {
this.selectedProduct = this.datenData.find(
daten => daten.qrcode === barcodeData.text
);
if (this.selectedProduct !== undefined) {
this.productFound = true;
this.setJson(this.fileName, this.object);
this.camerapreview();
this.showModal();
} else {
this.productFound = false;
this.router.navigate(['/tabs/tab2']);
this.toast
.show(`Product not found`, '5000', 'center')
.subscribe(toast => {
console.log(toast);
});
}
},
err => {
this.toast.show(err, '5000', 'center').subscribe(toast => {
console.log(toast);
this.router.navigate(['/tabs/tab2']);
});
}
);
}
setJson(fileName, object) {
this.file.writeFile(this.dataDirectory,this.fileName,
JSON.stringify(this.object), {append: true, replace: false});
}
}
data.json:
{
"jsondata": [
{
"id": 1,
"boolean": false,
"qrcode": "1",
"location": {
"latitude": 50.952952,
"longitude": 6.912467,
"street": "Venloer Str. 429"
},
"title": "Ohne dich würde ich mich nicht trauen.",
"artist": {
"name": "Jasmin Siddiqui und Falk Lehmann alias Herakut",
"website": "http://www.herakut.de"
},
"information": {
"text": "Auf dem Mural vom deutschen Street Art Duo Hera und Akut erkennt man ein kniendes Mädchen, die ihren Hund auf dem Arm hält. Ängstlich blickt sie in Richtung des Parks am Bürgerzentrum Ehrenfeld und hält ihren Hund schützend vor sich. Neben dem Hund steht „ohne dich würde ich mich nicht trauen“. Neben dem Mädchen kann man die Worte lesen: „we love even the scary looking ones“ . Man kann das Bild als einen Verweis auf das bunte und teils zwielichtige Treiben in naheliegenden Park verstehen.",
"gallery": {
"picturemap": "http://www.herakut.de/wp-content/uploads/2014/05/ko%CC%88ln.jpg",
"picturemapcredit": "http://www.herakut.de"
}
}
}
]
}
json.ts:
export interface Daten{
id: any;
boolean: boolean;
qrcode: string;
location: {
latitude: any;
longitude: any;
street: string;
};
title: string;
artist: {
name: string;
website: string;
};
information: {
text: string;
gallery: {
picturemap: string;
picturemapcredit: string;
};
};
}
Here is the github repository to it: https://github.com/alexandrasophiapetersen/BananAR-Cologne
The QR-Codes can be found in the assets folder.
This is my first Ionic Project. I would be very greatful, if someone could help me with this.
Thank you very much indeed.
I just looked through your code, its seems pretty well written.
That last commit where you tried to implement it has created a subtle bug:
With angular ngFor it loops on the actual tag you put it, not the contents, so you will end up with a list of ion-list, where what you had before was an ion-list with a list of ion-items inside.
You can use the ngIf
on the same row as as the ngFor
, and reference what you're looping on - if that's why you moved it.
For your actual issue I think you shouldn't be trying to turn the json file into some kind of database. Think of it more like a feed. You could easily put that json file onto a webserver and let every user load it in, and get automatic updates to the qr codes it supports, just by changing the web server file.
Putting individual users data inside isn't the right idea.
Instead you should look up a tutorial for Ionic Storage. It gives you a simple get set interface that, once configured in your project, will let you load the data in for that user only.
Keep a separate list. Your json has an id
field so you can just make an array of scanned codes and push the id into it. Then for each item you can check if the current item is already scanned before by seeing if the id of the current item is in that array.
I've kept this as a general advice as I assume with it being a uni project you want to learn for yourself, not risk getting a custom written solution just handed to you and trying to submit that. If you get stuck on bits though I can update my answer.
Some other thoughts while I browse the code:
naming the boolean boolean
is a shooting offence :P dont get into the habit of given awful names like that. Give it a descriptive name like isScanned
I see you have used some native toast plugin. Maybe you have a reason for that but there is actually a toast feature built in to Ionic. I'm not sure what your professor is grading you on but I would expect you to use the built in components where available.