I' m looking for a File chooser plugin for my ionic 5 app, but FileChooser is now unsupported by cordova. Are there other plugins that i can use. Thank you!
Does web API suit your needs instead of Cordova based approach?
it got decent support nowadays: https://caniuse.com/#search=FileReader
You could do it this way:
<ion-header>
<ion-toolbar>
<ion-title>
My super tabs app
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-card class="welcome-card">
<img [src]="imageUrl">
</ion-card>
<ion-button expand="full">
<ion-icon slot="start" name="image"></ion-icon>
<ion-label for="file-input">Choose file to upload</ion-label>
<input style="position: absolute; opacity: 0; width: 100%; height: 100%" type="file" (change)="loadImageFromDevice($event)" id="file-input" accept="image/png, image/jpeg">
</ion-button>
</ion-content>
Your ts:
import { Component } from '#angular/core';
import { DomSanitizer, SafeResourceUrl } from '#angular/platform-browser';
#Component({
selector: 'app-tab1',
templateUrl: 'tab1.page.html',
styleUrls: ['tab1.page.scss']
})
export class Tab1Page {
imageUrl: SafeResourceUrl;
dataUrl: string | ArrayBuffer;
constructor(private domSanitizer: DomSanitizer) {}
loadImageFromDevice = (event) => {
if (!event.target.files[0]) return;
const file = event.target.files[0];
if (!file.type.match('image')) return;
// do blob:
let blobReader = new FileReader();
blobReader.readAsArrayBuffer(file);
blobReader.onload = () => {
let blob: Blob = new Blob([new Uint8Array((blobReader.result as ArrayBuffer))]);
this.imageUrl = this.domSanitizer.bypassSecurityTrustResourceUrl(URL.createObjectURL(blob));
};
// do base64data:
/* let dataReader = new FileReader();
dataReader.readAsDataURL(file);
dataReader.onload = () => {
this.dataUrl = dataReader.result;
};
dataReader.onerror = (error) => {
console.log(error)
}; */
// handle errors:
blobReader.onerror = (error) => {
console.log(error)
};
};
}
This will leverage standard web API (input file) and recently all modern browsers / devies support this approach.
Definitely depends on your use case and for some it won't work.
Demo: https://stackblitz.com/edit/ionic-4-angular-8-start-template-ywc4r8
I am a child with an application with Ionic 4, my application is already logging in with Email, Facebook and Google using Firebase. I created a comments page and the comments are already being saved in Firestore and being displayed on a page. Wow do I get the logged in user data and insert it in this page. Comments?
I used the following solution:
JS:
in the builder
fireAuth.user.subscribe((data => {
this.user = data;
}));
Methods
listarComentarios() {
this.crudService.read_Comentarios().subscribe(data => {
this.comentarios = data.map(e => {
return {
id: e.payload.doc.id,
isEdit: false,
Comentario: e.payload.doc.data()['Comentario'],
Usuario: e.payload.doc.data()['Usuario'],
Foto: e.payload.doc.data()['Foto']
};
})
console.log(this.comentarios);
});
CreateRecord() {
let record = {};
record['Comentario'] = this.comentarioUsuario;
record['Usuario'] = this.user.displayName
record['Foto'] = this.user.photoURL
this.crudService.create_NewComentario(record).then(resp => {
this.comentarioUsuario = "";
this.user.displayName = "";
this.user.photoURL = "";
console.log(resp);
})
.catch(error => {
console.log(error);
});
HTML:
<ion-content>
<ion-grid *ngFor="let item of comentarios">
<span *ngIf="!item.isEdit; else elseBlock">
<!-- this rows will represent sample comments -->
<ion-row class="post-content">
<ion-col size="2" >
<ion-avatar class="ion-align-self-start">
<img class="icon-photo" [src]="item.Foto">
</ion-avatar>
</ion-col>
<ion-col size="6">
<div>
<p><strong>{{item.Usuario}} </strong>{{item.Comentario}}</p>
</div>
</ion-col>
<ion-col>
Currently I have designed the page that contains the form to get the details from the user. The last field is the attachment field where the user can attach the files such as PDF and image files from camera and Gallery. For that purpose, I am using fab list with three buttons.
Now the problem is that when I opens the fab, it remains open even if I am moving to next page and returns back to this current page. I am using bottom tab menu to navigate between the pages in the app. What I would like to have is that, as soon as I leave this page, the fab list of button should close automatically, even if it remains open at the time of moving to next page.
I have tried many method such as this.fab.close() and fab.close() at the form reset method, but none works. I need the fab to get close each and every time I leaves the current page and return back to this current page.
Here's what I have tried:
Mypage.html:
<ion-header color="purple">
<ion-navbar hideBackButton="true" color="purple">
<ion-title>
{{title}}
</ion-title>
<span class="titlesmall" *ngIf="hideEmail">
{{email}}
</span>
<ion-buttons right>
<button ion-button icon-only (click)="logoutWithConfirmation()">
<ion-icon name="log-out"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content class="ioncontent-background" scroll="true" >
<form [formGroup]="form" >
<ion-row>
<ion-item>
<ion-icon class="icon-in" name="options" item-left></ion-icon>
<ion-label color="textcolor" floating>Category</ion-label>
<ion-select [(ngModel)]="vm.SupportCategory" class="textcolor" formControlName="category" (change)="onChange(vm.SupportCategory)">
<ion-option *ngFor="let item of list" [value]="item.key" >{{item.value}}</ion-option>
</ion-select>
</ion-item>
<div class="error-message-support" *ngIf="form.controls.category.errors && (form.controls.category.dirty || form.controls.category.touched)">
<span *ngIf="form.controls.category.errors?.required">Category is required</span>
</div>
</ion-row>
<ion-row>
<ion-item>
<ion-icon class="icon-in" name="create" item-left></ion-icon>
<ion-label color="textcolor" floating> Subject</ion-label>
<ion-input type="text" [(ngModel)]="vm.Subject" class="textcolor" formControlName="subject" tabindex="1" (keyup)="moveFocus($event,query, false)"></ion-input>
</ion-item>
<div class="error-message-support" *ngIf="form.controls.subject.errors && (form.controls.subject.dirty || form.controls.subject.touched)">
<span *ngIf="form.controls.subject.errors?.required">Subject is required</span>
</div>
</ion-row>
<ion-row>
<ion-item>
<ion-icon class="icon-in" name="help" item-left></ion-icon>
<ion-label color="textcolor" floating>Query</ion-label>
<ion-input type="text" [(ngModel)]="vm.Query" class="textcolor" formControlName="query" tabindex="1" (keyup)="moveFocus($event,moreinfo, false)"
#query></ion-input>
</ion-item>
<div class="error-message-support" *ngIf="form.controls.query.errors && (form.controls.query.dirty || form.controls.query.touched)">
<span *ngIf="form.controls.query.errors?.required">Query is required</span>
</div>
</ion-row>
<ion-row>
<ion-item>
<ion-icon class="icon-in" name="quote" item-left></ion-icon>
<ion-label color="textcolor" floating>More Information</ion-label>
<ion-input type="text" [(ngModel)]="vm.MoreInformation" class="textcolor" formControlName="moreinfo" tabindex="1"
[attr.required]="true" (keyup)="moveFocus($event,submitbutton, true)" #moreinfo></ion-input>
</ion-item>
<div class="error-message-support" *ngIf="form.controls.moreinfo.errors && (form.controls.moreinfo.dirty || form.controls.moreinfo.touched)">
<span *ngIf="form.controls.moreinfo.errors?.required">Query is required</span>
</div>
</ion-row>
<ion-row no-lines class="fab-icon">
<ion-col col-2>
<ion-icon name="md-attach" color="white" class="icon-in" item-left></ion-icon>
</ion-col>
<ion-col col-8 >
<span class="span-style-fab">{{vm.attach}}</span>
</ion-col>
<ion-col col-2>
<ion-fab right class="ion-fab-right" #fab>
<button ion-fab mini color = "purple" (click)="click($event,fab)">
<ion-icon [name]="isAdded ? 'close' : 'add'" id="changeicon"></ion-icon>
</button>
<ion-fab-list side="top">
<button ion-fab class="fab-color" (click)="onCameraClick(1,fab)">
<ion-icon color="white" name="camera"></ion-icon>
</button>
<button ion-fab class="fab-color" (click)="onCameraClick(2,fab)">
<ion-icon color="white" name="images"></ion-icon>
</button>
<button ion-fab class="fab-color" (click)="fileattach(fab)">
<ion-icon color="white" name="document"></ion-icon>
</button>
</ion-fab-list>
</ion-fab>
</ion-col>
</ion-row>
<!-- <ion-row class="fab-icon" col-12>
<ion-col col-2>
<ion-icon name="md-attach" color="white" class="icon-in" item-left></ion-icon>
</ion-col>
<ion-col col-8>
<span class="span-style-fab">{{vm.attach}}</span>
</ion-col>
<ion-col col-2>
<ion-fab right class="ion-fab-right" #myfab>
<button ion-fab mini color="purple" (click)="click($event)">
<ion-icon [name]="isAdded ? 'close' : 'add'" id="changeicon"></ion-icon>
</button>
<ion-fab-list side="top" >
<button ion-fab class="fab-color" (click)="onCameraClick(1,fab)">
<ion-icon color="white" name="camera"></ion-icon>
</button>
<button ion-fab class="fab-color" (click)="onCameraClick(2,fab)">
<ion-icon color="white" name="images"></ion-icon>
</button>
<button ion-fab class="fab-color" (click)="fileattach(fab)">
<ion-icon color="white" name="document"></ion-icon>
</button>
</ion-fab-list>
</ion-fab>
</ion-col>
</ion-row> -->
<ion-item>
<div class="button-bar">
<button ion-button icon-end name="submitbutton" (click)="submit()" class="button" color="purple">
Submit
<ion-icon name="md-checkmark-circle"></ion-icon>
</button>
</div>
</ion-item>
</form>
</ion-content>
Mypage.ts:
import { Component, NgZone,ViewChild } from '#angular/core';
import { NavController, App, AlertController, Events, FabContainer } from 'ionic-angular';
import { FormControl, Validators, FormGroup, AbstractControl } from '#angular/forms';
import { Support } from '../../models/support';
import { isNullOrUndefined } from 'util';
import { MessageService } from "../../services/message.service";
import { Camera, CameraOptions } from '#ionic-native/camera';
import { Keyboard } from '#ionic-native/keyboard';
import { FileChooser } from '#ionic-native/file-chooser';
import { FileOpener } from '#ionic-native/file-opener';
import { FilePath } from '#ionic-native/file-path';
import { SupportService } from '../../services/support.service';
import { FileTransfer} from '#ionic-native/file-transfer';
import { File } from '#ionic-native/file';
import { Base64 } from '#ionic-native/base64';
import { BroadCastService } from '../../services/broadcast.service';
import { AuthenticationService } from '../../services/authentication.service';
#Component({
selector: 'page-support',
templateUrl: 'support.html',
providers: [AuthenticationService, MessageService, Camera, SupportService, FileChooser, FileOpener, FilePath, FileTransfer, File, Base64]
})
export class SupportPage {
#ViewChild('myfab') fabRef: FabContainer;
vm: Support;
// private platform: Platform; public app: App;
service: any;
form: FormGroup;
list = [];
public n: any;
files: any[];
support = new Support();
fab: FabContainer;
message: any;
todayDate: any;
newFileName: any;
public dateToday: any;
createFile: AbstractControl;
value: any;
photoencodetype: number;
datas: any;
filetypename: any;
isAdded: boolean = false;
changeicon: any = "add";
attach: any;
public unregisterBackButtonAction: any;
constructor(public navCtrl: NavController,
private camera: Camera,
private keyboard: Keyboard, private zone: NgZone,
public authService: SupportService,
public alertctr: AlertController,
authenticationservice: SupportService,
public logoutservice: AuthenticationService,
private filechooser: FileChooser,
public broadCastService: BroadCastService,
private filepath: FilePath,
private base64: Base64,
message: MessageService,
private event: Events,
public app: App) {
this.vm = new Support();
this.files = [];
this.message = message;
this.vm.attach = "Attachment:";
this.isAdded = false;
authenticationservice.category().subscribe(res => {
if (!isNullOrUndefined(res)) {
this.list = res;
}
});
}
ionViewDidLoad() {
console.log('support page - ionViewDidLoad');
this.keyboard.onKeyboardShow().subscribe(() => this.event.publish('hideTabs'));
this.keyboard.onKeyboardHide().subscribe(() => this.event.publish('showTabs'));
}
showAlert() {
let alert = this.alertctr.create({
title: `Greetings`,
message: `
<p>My Message</p>
<p>My Message here</p>
<p>The Home-Connect Team</p>
`,
buttons: ['Continue']
});
alert.present();
}
submit() {
if (this.form.valid) {
this.support.Subject = this.vm.Subject;
this.support.Query = this.vm.Query;
this.support.MoreInformation = this.vm.MoreInformation;
this.support.SupportAttachmentMapping = this.files;
this.support.SupportCategory = this.vm.SupportCategory;
this.support.UserId = localStorage.getItem('userid');
this.authService.support(this.support).subscribe(res => {
if (!isNullOrUndefined(res)) {
console.log("Message" + res);
if (res.status == 200) {
this.value = "Your ticket has been submitted successfully";
this.ticketsuccess(this.value);
this.refresh();
} else {
this.value = "Your ticket has not been submitted";
this.ticketsuccess(this.value);
this.refresh();
}
}
}, err => {
alert(JSON.stringify(err));
});
} else {
this.validateFormControl(this.form);
}
}
fileattach(fab: FabContainer) {
fab.close();
//const fileTransfer: FileTransferObject = this.transfer.create();
this.filechooser.open().then(file => {
this.filepath.resolveNativePath(file).then(resolvedFilepath => {
// this.fileopener.open(resolvedFilepath, 'application/pdf').then(value => {
let name = resolvedFilepath.split("/");
let currentName = name[name.length - 1];
let fileextension = currentName.split(".")[1].toUpperCase();
if (currentName.split(".")[1].toUpperCase() == "PNG" || currentName.split(".")[1].toUpperCase() == "PDF"
|| currentName.split(".")[1].toUpperCase() == "JPG") {
let filePath: string = resolvedFilepath;
this.base64.encodeFile(filePath).then((base64File: string) => {
console.log(base64File);
if (fileextension == "PNG") {
this.filetypename = "image/png";
} else if (fileextension == "PDF") {
this.filetypename = "application/pdf";
}else if (fileextension == "JPG") {
this.filetypename = "application/jpg";
}
this.files = [];
this.files.push({ FileName: currentName, FileExtention: this.filetypename, FileType: this.filetypename, FileData: base64File });
this.vm.attach = currentName;
this.attach = this.vm.attach;
this.isAdded = true;
}, (err) => {
console.log(err);
});
}
else {
alert("The file being uploaded needs to be of type png or jpg or pdf Format.");
}
}).catch(err => {
// alert(JSON.stringify(err));
console.log(JSON.stringify(err));
});
}).catch(err => {
console.log(JSON.stringify(err));
});
}
ticketsuccess(value: any) {
let alert = this.alertctr.create({
cssClass: 'alert-message',
title: 'Submission',
message: value,
buttons: [
{
text: 'Okay',
handler: () => {
console.log('Buy clicked');
this.resetForm(this.form);
this.broadCastService.broadCastSupportCreated("Your ticket has been submitted successfully");
}
}
]
});
alert.present();
}
ngOnInit() {
this.initializeValidators();
}
click(event, fab: FabContainer) {
if (this.isAdded) {
fab.close();
let alert = this.alertctr.create({
cssClass: 'alert-confirmation',
title: 'Confirm Remove!',
message: 'Are you sure you want to remove the attachement ?',
buttons: [
{
text: 'No',
handler: () => {
console.log('Cancel clicked');
fab.close();
}
},
{
text: 'Yes',
handler: () => {
this.isAdded = false;
this.files = [];
this.vm.attach = "Attachment";
fab.close();
}
}
]
});
alert.present().then(() => {
fab.close();
});
}
}
initializeValidators() {
this.form = new FormGroup({
category: new FormControl('', Validators.required),
subject: new FormControl('', [Validators.required]),
query: new FormControl('', [Validators.required]),
moreinfo: new FormControl('', null),
attachment: new FormControl('', null)
});
this.form.controls['moreinfo'].markAsTouched();
// this.form.controls['attachment'].markAsTouched();
}
ionViewDidEnter() {
this.resetForm(this.form)
}
validateFormControl(formGroup: FormGroup) {
Object.keys(formGroup.controls).forEach(field => {
const control = formGroup.get(field);
if (control instanceof FormControl) {
control.markAsTouched({ onlySelf: true });
} else if (control instanceof FormGroup) {
this.validateFormControl(control);
}
});
}
resetForm(formGroup: FormGroup) {
let control: AbstractControl = null;
formGroup.reset();
// this.vm.Subject = '';
// this.vm.Query = '';
// this.vm.MoreInformation= '';
// this.vm.SupportCategory= '';
formGroup.markAsUntouched();
this.vm.attach = "Attachment";
this.isAdded = false;
Object.keys(formGroup.controls).forEach((name) => {
control = formGroup.controls[name];
control.setErrors(null);
});
this.initializeValidators();
}
moveFocus(event, nextElement, isLastControl, fab: FabContainer) {
if (event.key === 'Enter') {
if (isLastControl && isLastControl === true) {
this.keyboard.hideKeyboardAccessoryBar(true);
this.refresh();
this.submit();
} else {
nextElement.setFocus();
}
}
}
createFileName() {
this.todayDate = new Date();
this.dateToday = (this.todayDate.getFullYear() + '-' + ((this.todayDate.getMonth() + 1)) + '-' + this.todayDate.getDate() + ' ' + this.todayDate.getHours() + ':' + this.todayDate.getMinutes() + ':' + this.todayDate.getSeconds()),
this.newFileName = "Support " + this.dateToday;
return this.newFileName;
}
refresh(fab?: FabContainer): void {
if (fab !== undefined) {
fab.close();
}
}
onCameraClick(sourceType, fab: FabContainer) {
fab.close();
const options: CameraOptions = {
quality: 25,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
sourceType: sourceType
};
this.camera.getPicture(options).then((imageUri) => {
console.log(imageUri);
// alert('Test' + this.camera.EncodingType.JPEG);
// this.photoencodetype = this.camera.EncodingType.JPEG;
this.files = [];
let currentName = this.createFileName() + "" + ".jpg";
let base64Image = 'data:image/jpg;base64,' + imageUri;
this.files.push({ FileName: currentName, FileExtention: "image/jpg", FileType: "image/jpg", FileData: base64Image });
// this.createFileName = this.newFileName;
// currentName = this.form.controls['attachment'];
// this.message.alert('Uploaded Successfully '+ currentName);
this.vm.attach = currentName;
this.attach = this.vm.attach;
this.isAdded = true;
}, (error) => {
console.log(error);
});
}
}
I have also attached the coding for the tabs page that I am using to navigate between the pages.
mytab.ts:
#Component({
templateUrl: 'tabs.html',
selector: 'page-tabs',
providers: [AuthenticationService, HomeService, BroadCastService]
})
export class TabsPage{
#ViewChild('myTabs') tabRef: Tabs;
#ViewChild('fab') fabRef: FabContainer;
changePasswordPage = ChangePasswordPage;
title: string;
email: string;
dashboardpageTab = DashboardPage;
supportpageTab = SupportPage;
cancellationTab = CancellationPage;
serviceChangeTab = ServiceChangePage;
shoppingTab = ShoppingPage;
myprofileTab = MyprofilePage;
accounttransfertab = AccounttransferPage;
changePasswordTab = ChangePasswordPage;
aboutTab = AboutPage;
userid: string;
isEmpty: boolean;
hideEmail: boolean = true;
bankdetail: BankingDetails[];
fabMenuIsOpened: boolean = false;
hideFabmenu: boolean = true;
public alertShown: boolean = false;
mb: any;
applicationlist = new ApplicationList();
subscription: ISubscription;
constructor(public navCtrl: NavController, private zone: NgZone,
private elementRef: ElementRef,
private alertCtrl: AlertController,
public app: App, private platform: Platform,
private event: Events,
private renderer: Renderer,
public homeservice: HomeService,
private authService: AuthenticationService,
private broadCastService: BroadCastService,
private userSessionService: UserSessionService) {
this.title = this.userSessionService.referenceNumber();
this.email = this.userSessionService.email();
this.subscription = this.broadCastService.onChangePassword()
.subscribe(message => {
this.logout();
});
this.broadCastService.onSupportCreated()
.subscribe(message => {
this.tabRef.select(0);
});
platform.registerBackButtonAction(() => {
if (this.alertShown === false) {
let nav = app.getActiveNavs()[0];
let activeView = nav.getActive();
console.log('activeView => ' + activeView.name);
// alert(activeView.name);
if (activeView.name !== 'DashboardPage') {
this.goToDashBoardPage();
} else if (activeView.name === 'DashboardPage') {
this.logoutmethod();
} else {
nav.pop();
}
}
}, 0);
}
ionViewDidLeave() {
this.subscription.unsubscribe();
}
ionViewDidEnter() {
let tabs = this.queryElement(this.elementRef.nativeElement, '.tabbar');
let fabmenu = this.queryElement(this.elementRef.nativeElement, 'ion-fab');
this.event.subscribe('hideTabs',
() => {
console.log('tabs page - hideTabs');
this.renderer.setElementStyle(fabmenu, 'display', 'none');
this.renderer.setElementStyle(tabs, 'display', 'none');
let selectTab = this.tabRef.getSelected()._elementRef.nativeElement;
let content = this.queryElement(selectTab, '.scroll-content');
this.mb = content.style['margin-bottom'];
this.renderer.setElementStyle(content, 'margin-bottom', '0');
});
this.event.subscribe('showTabs',
() => {
console.log('tabs page - showTabs');
this.renderer.setElementStyle(tabs, 'display', '');
this.renderer.setElementStyle(fabmenu, 'display', '');
let selectTab = this.tabRef.getSelected()._elementRef.nativeElement;
let content = this.queryElement(selectTab, '.scroll-content');
this.renderer.setElementStyle(content, 'margin-bottom', this.mb);
});
}
queryElement(elem: HTMLElement, q: string): HTMLElement {
return <HTMLElement>elem.querySelector(q);
}
logoutmethod() {
this.logoutWithConfirmation();
}
goToDashBoardPage() {
this.zone.run(() => {
this.tabRef.select(0);
});
}
public onTabsChange() {
this.fabRef.close();
this.fabMenuIsOpened = false;
this.title = this.tabRef.getSelected().index === 0 ?
this.userSessionService.referenceNumber() : this.tabRef.getSelected().tabTitle;
this.hideEmail = this.tabRef.getSelected().index === 0;
}
getOverlayStyle() {
let myStyles = {
'width': '100%',
'height': '100%',
'display': 'flex',
'justify-content': 'flex-end',
'align-items': 'flex-end',
'position': 'absolute',
'background-color': 'rgba(0, 0, 0, 0.7)',
'z-index': 99,
'bottom': '0px',
'right': '0px',
'padding-right': '10px',
'padding-bottom': '10px'
};
return this.fabMenuIsOpened ? myStyles : {};
}
tab(fab: FabContainer) {
this.fabMenuIsOpened = !this.fabMenuIsOpened;
if (this.fabMenuIsOpened) {
console.log('Opened...');
} else {
console.log('Closed...');
}
}
logoutWithConfirmation() {
let alert = this.alertCtrl.create({
cssClass: 'alert-confirmation',
title: 'Confirm Logout',
message: 'Do you want to logout ?',
buttons: [
{
text: 'No',
handler: () => {
console.log('Cancel clicked');
this.alertShown = false;
}
},
{
text: 'Yes',
handler: () => {
this.authService.logOut();
//this.platform.exitApp();
this.navCtrl.push(LoginPage);
}
}
]
});
alert.present().then(() => {
this.alertShown = true;
});
}
logout() {
this.authService.logOut();
this.navCtrl.push(LoginPage);
}
tabmenu(event, fab: FabContainer) {
this.fabMenuIsOpened = !this.fabMenuIsOpened;
fab.close();
this.tabRef.select(event);
if (this.fabMenuIsOpened) {
console.log('Opened...');
} else {
console.log('Closed...');
}
}
IonSelect(val: string) {
this.title = val;
}
contentSettings = {
theme: 'android'
};
}
this works ok for me !!
html...
<ion-fab top right edge #fab >
<button ion-fab mini class="menu">
<ion-icon ios="md-more" name="more" md="md-more"></ion-icon>
</button>
<ion-fab-list>
<button ion-fab (click)="closeFab(fab)">
<ion-icon name="md-camera" style="color:#761cca;">
</ion-icon>
</button>
</ion-fab-list>
</ion-fab>
ts...
import { FabContainer} from 'ionic-angular';
closeFab(fab: FabContainer) {
fab.close();
}
I seem to have trouble displaying images in the Image Gallery on Android. The PhotoLibrary plugin returns the list of files, but when I feed the image URLs to img tags, they don't load.
window['cordova']['plugins']['photoLibrary'].getLibrary(
result => console.log(libraryItem),
err => console.log(err);
},
{
thumbnailWidth: 512,
thumbnailHeight: 384,
quality: 0.8,
includeAlbumData: true
});
This will retrieve the URLs to the images, but they can't be used to actually display them. I get things like:
creationDate: Fri Nov 03 2017 20:06:01 GMT-0400 (EDT)
fileName: "2017-10-4-1.jpg"
height: 960
id: "1907;/storage/emulated/0/Pictures/Timelapser/2017-10-4-1.jpg"
latitude: 0
longitude: 0
photoURL: "cdvphotolibrary://photo?photoId=1907%3B%2Fstorage%2Femulated%2F0%2FPictures%2FTimelapser%2F2017-10-4-1.jpg"
thumbnailURL: "cdvphotolibrary://thumbnail?photoId=1907%3B%2Fstorage%2Femulated%2F0%2FPictures%2FTimelapser%2F2017-10-4-1.jpg&width=512&height=384&quality=0.8"
width: 1280
Feeding photoURL or thumbnailURL to img src doesn't work. I tried to decodeURI them, use the part before or after the ; and nothing.
You need to use Native Photo Library plugin and cdvphotolibrary pipe as shown below.
Here is working Git project
html
<ion-grid no-padding margin-top>
<ion-row class="row">
<ion-col col-6 *ngFor="let data of library">
<img [src]="data?.thumbnailURL | cdvPhotoLibrary">
</ion-col>
</ion-row>
</ion-grid>
ts
//fetch Photos
fetchPhotos() {
this.platform.ready().then(() => {
this.library = [];
this.photoLibrary.getLibrary({ thumbnailWidth: THUMBNAIL_WIDTH, thumbnailHeight: THUMBNAIL_HEIGHT }).subscribe({
next: (chunk) => {
this.library = this.library.concat(chunk);
this.cd.detectChanges();
},
error: (err: string) => {
if (err.startsWith('Permission')) {
this.platform.ready().then(() => {
this.photoLibrary.requestAuthorization({ read: true })
.then(() => {
}).catch((err) => {
let message = 'requestAuthorization error: ${err}';
this.showToast.showErrorToast(message);
});
});
} else { // Real error
let message: 'getLibrary error: ${err}';
this.showToast.showErrorToast(message);
}
},
complete: () => {
// Library completely loaded
}
});
});
}
cdv-photo-library.ts (pipe)
import { Pipe, PipeTransform } from '#angular/core';
import { DomSanitizer } from '#angular/platform-browser';
#Pipe({
name: 'cdvPhotoLibrary',
})
export class CdvPhotoLibraryPipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) { }
transform(url: string) {
if (url != null) {
return url.startsWith('cdvphotolibrary://') ? this.sanitizer.bypassSecurityTrustUrl(url) : url;
}
}
}
I want to upload file from my ionic application to server. I am using cordovafiletransfer plugin. Using that I am able to upload file by providing static path in controller code. My question is how to get selected file path by user? I only get filename from input tag on the relative path of selected file. How to get that?
View Page Code:
<label class="item item-input">
<div class="input-label">Upload Photo</div>
<input type="file" onchange="angular.element(this).scope().setFile(this)" accept="image/*"/>
</label>
<div class="padding">
<button ng-click="upload()" class="button button-block button-assertive">Upload</button>
</div>
Controller Code:
$scope.upload = function() {
var filename, options, targetPath;
console.log($scope.theFile);
targetPath = cordova.file.externalRootDirectory + '/Download/androidify.png';
filename = targetPath.split('/').pop();
options = {};
options.fileKey = 'image_file';
options.fileName = $scope.theFile.name;
options.chunkedMode = false;
options.mimeType = $scope.theFile.type;
options.headers = {
'Authorization': getDeviceToken()
};
console.log(options);
return $cordovaFileTransfer.upload(domain.uploadphoto(), targetPath, options).then(
(function(result) {
console.log('SUCCESS: ' + JSON.stringify(result.response));
}),
(function(err) {
console.log('ERROR: ' + JSON.stringify(err));
}),
function(progress) {}
);
};
$scope.setFile = function(element) {
return $scope.$apply(function($scope) {
console.log(element);
return $scope.theFile = element.files[0];
});
};
How to get proper target path of selected file?
I came across this post which should solve the problem, (it works for me, with some modification):
In my template:
<input type="file" fileread="file.path" />
<button type="button" class="button button-small button-assertive" ng-click="vm.upload(file)">Upload PDF</button>
and my modified Directive:
.directive("fileread", ['$cordovaFile', function ($cordovaFile) {
return {
scope: {
fileread: "="
},
link: function (scope, element, attributes) {
element.bind("change", function (changeEvent) {
var reader = new FileReader();
reader.onload = function (loadEvent) {
var fileName = changeEvent.target.files[0].name;
$cordovaFile.writeFile(cordova.file.dataDirectory, fileName, loadEvent.target.result, true)
.then(function (result) {
console.log(result)
}, function (err) {
console.warn(err)
});
scope.$apply(function () {
scope.fileread = cordova.file.dataDirectory + fileName;
});
}
reader.readAsArrayBuffer(changeEvent.target.files[0]);
});
}
}
}]);
Remember to clean up after you uploaded the document
use:
$cordovaFile.removeFile(cordova.file.dataDirectory, fileName)
.then(function (success) {
// success
}, function (error) {
// error
});
Also see http://www.javascripture.com/FileReader for more info regarding FileReader