Angular 6, Firebase Storage web Image gallery - firebase

I've got a problem with downloading URL during uploading an image file.
I want to use this url to show this images from Firebase storage.
Uplad is working, because i can see this photos on my storage on firebase, but i can't download it and show in my web
Here's a upload.service.ts
import { Injectable } from '#angular/core';
import { AngularFireModule } from 'angularfire2';
import { GalleryImage } from '../models/galleryImage.model';
import { AngularFireDatabase} from 'angularfire2/database';
import { FirebaseListObservable, FirebaseObjectObservable } from 'angularfire2/database-deprecated';
import { Upload } from '../models/upload.model';
import * as firebase from 'firebase';
#Injectable()
export class UploadService {
private basePath = '/uploads';
private uploads: FirebaseListObservable<GalleryImage[]>;
constructor(private ngFire: AngularFireModule, public db: AngularFireDatabase) { }
uploadFile(upload: Upload) {
const storageRef = firebase.storage().ref();
const uploadTask = storageRef.child(`${this.basePath}/${upload.file.name}`)
.put(upload.file);
uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
// three observers
// 1.) state_changed observer
(snapshot) => {
// upload in progress
upload.progress = (uploadTask.snapshot.bytesTransferred / uploadTask.snapshot.totalBytes) * 100;
console.log(upload.progress);
},
// 2.) error observer
(error) => {
// upload failed
console.log(error);
},
// 3.) success observer
(): any => {
uploadTask.snapshot.ref.getDownloadURL().then(function(downloadURL) {
upload.url = downloadURL;
console.log('FirstURL', downloadURL);
console.log('SecondURL', upload.url);
this.saveFileData(upload);
});
}
);
}
private saveFileData(upload: Upload) {
this.db.list(`${this.basePath}/`).push(upload);
console.log('File saved at' + upload.url);
}
}
Here's my image.service.ts
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFireDatabase } from 'angularfire2/database';
import { FirebaseApp } from 'angularfire2';
import 'firebase/storage';
import { GalleryImage } from '../models/galleryImage.model';
import * as firebase from 'firebase';
#Injectable()
export class ImageService {
private uid: string;
constructor(private afAuth: AngularFireAuth, private db: AngularFireDatabase) {
this.afAuth.authState.subscribe(auth => {
if (auth !== undefined && auth !== null) {
this.uid = auth.uid;
}
});
}
getImages(): Observable<GalleryImage[]> {
return this.db.list('uploads').valueChanges();
}
getImage(key: string) {
return firebase.database().ref('uploads/' + key).once('value')
.then((snap) => snap.val());
}
}
Here's my upload.model.ts
export class Upload {
$key: string;
file: File;
url: string;
progress: number;
createdOn: Date = new Date();
name: string;
constructor(file: File) {
this.file = file;
}
}

Related

Ionic 4 & Firebase integration

So, I'm quite a noob when it comes to ionic 4 firebase integration. Basically I've managed to get the firebase authentication to work, but the problem is I can't seem to save the user's input in the sign up page to firebase database. I need it to work as I would like to link the user to his/her checklist.
This is my sign-up page.ts
import { Component, OnInit } from '#angular/core';
import { Router } from "#angular/router";
import { Platform, AlertController } from '#ionic/angular';
import { LoadingController, ToastController } from '#ionic/angular';
import { AngularFireAuth } from '#angular/fire/auth';
//disable side menu
import { MenuController } from '#ionic/angular';
#Component({
selector: 'app-signup',
templateUrl: './signup.page.html',
styleUrls: ['./signup.page.scss'],
})
export class SignupPage implements OnInit {
email: string = '';
password: string = '';
error: string = '';
username: string = '';
constructor(
private fireauth: AngularFireAuth,
public router: Router,
public menuCtrl: MenuController,
private toastController: ToastController,
private platform: Platform,
public loadingController: LoadingController,
public alertController: AlertController
) { }
async openLoader() {
const loading = await this.loadingController.create({
message: 'Please Wait ...',
duration: 2000
});
await loading.present();
}
async closeLoading() {
return await this.loadingController.dismiss();
}
signup() {
this.fireauth.auth.createUserWithEmailAndPassword(this.email, this.password)
.then(res => {
if (res.user) {
console.log(res.user);
this.updateProfile();
}
})
.catch(err => {
console.log(`login failed ${err}`);
this.error = err.message;
});
}
updateProfile() {
this.fireauth.auth.onAuthStateChanged((user) => {
if (user) {
console.log(user);
user.updateProfile({
displayName: this.username
})
.then(() => {
this.router.navigateByUrl('/login');
})
}
})
}
async presentToast(message, show_button, position, duration) {
const toast = await this.toastController.create({
message: message,
showCloseButton: show_button,
position: position,
duration: duration
});
toast.present();
}
ionViewWillEnter (){
this.menuCtrl.enable(false);
}
ngOnInit(){}
}
Actually, you aren't using the firebase database. The user.updateProfile method stores the displayName property in the Firebase Auth system. That information is saved in the Firebase Auth system.

IONIC 4 - The event ionViewWillEnter only fires once

Please, I am building a Sidemenu Ionic app with firebase firestore, when it opens, the app shows my collections and data, but when browsing between pages with sidemenu and returning to the data page, there is no data return nothing, I need to refresh a browser page to see the data again. I already checked the life cycle and the ionViewWillEnter the event only fires once.
import { Component, OnInit } from '#angular/core';
import { Evento, EventoService} from 'src/app/services/evento.service';
import { Router, RouterEvent } from '#angular/router';
import { LoadingController, NavController } from '#ionic/angular';
#Component({
selector: 'app-eventos',
templateUrl: './eventos.page.html',
styleUrls: ['./eventos.page.scss'],
})
export class EventosPage{
eventos: Evento[];
pages = [
{
url: '/menu/eventos',
}
];
selectedPath = '';
constructor(private eventoService: EventoService, private router: Router,
private loadingController: LoadingController, private navCtrl: NavController) {
this.navCtrl.setDirection('root');
}
ionViewWillEnter(){
console.log(' Teste 3: ionViewWillEnter ')
this.eventoService.getAllEventos().subscribe(res => {
this.eventos = res;
let dateString = 'item.data';
let newDate = new Date(dateString);
this.loadEvento();
});
}
async loadEvento() {
const loading = await this.loadingController.create({
message: 'Carregando eventos...',
spinner: 'crescent',
duration: 300
});
return await loading.present();
}
}
<ion-header>
<ion-toolbar color="primary">
<ion-buttons slot="start">
<ion-menu-button></ion-menu-button>
</ion-buttons>
<ion-title>Eventos</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<ion-card class="card" *ngFor="let item of eventos" lines="inset" button [routerLink]="['/detailsEvento', item.id]"
routerdirection="forward">
<ion-card-header>
<ion-card-title class="texto"> {{item.nome}}</ion-card-title>
<ion-card-title class="texto"> Data: {{item.data | date:'dd/MM/yyyy'}}</ion-card-title>
</ion-card-header>
</ion-card>
</ion-content>
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { FormsModule } from '#angular/forms';
import { Routes, RouterModule } from '#angular/router';
import { IonicModule } from '#ionic/angular';
import { EventosPage } from './eventos.page';
import { FontAwesomeModule } from '#fortawesome/angular-fontawesome';
const routes: Routes = [
{
path: '',
component: EventosPage
}
];
#NgModule({
imports: [
FontAwesomeModule,
CommonModule,
FormsModule,
IonicModule,
RouterModule.forChild(routes)
],
declarations: [EventosPage]
})
export class EventosPageModule {}
import { Injectable } from '#angular/core';
import { AngularFirestore, AngularFirestoreCollection } from 'angularfire2/firestore';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
export interface Evento {
nome: string;
data: string;
horario: string;
local: string;
descricao: string;
}
#Injectable({
providedIn: 'root'
})
export class EventoService {
private eventosCollection: AngularFirestoreCollection<Evento>;
private eventos: Observable<Evento[]>;
constructor(db: AngularFirestore) {
this.eventosCollection = db.collection<Evento>('eventos', ref => ref.orderBy('data'));
this.eventos = this.eventosCollection.snapshotChanges().pipe(
map(actions => {
return actions.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
return{ id, ...data };
});
})
);
}
getAllEventos(){
return this.eventos;
}
getEvento(id){
return this.eventosCollection.doc<Evento>(id).valueChanges();
}
}
constructor(
private afStore: AngularFirestore,
private router: Router,
) {
this.router.events.subscribe((evt) => {
if (evt instanceof NavigationEnd && this.router.url === '/main-screen/home')
{
this.storage.get('userInfo').then((val) => {
if (val) {
// console.log(val);
this.profesion = val.Profesion ? val.Profesion : 'popular';
if ( this.profesion === 'popular') {
this.allCollectionVideo();
} else {
this.getDefaultProfesion(this.profesion);
}
}
});
}
});
}
It can resolve your issue.

how to resolve Runtime Error: TypeError: Cannot read property 'ready' of undefined?

app.component.ts
import { Component, ViewChild } from '#angular/core';
import { Platform, NavController } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { Storage } from '#ionic/Storage';
import { HomePage } from '../pages/home/home';
import { LoginPage } from '../pages/login/login';
import { RegisterPage } from '../pages/register/register';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
_platform: Platform;
public get platform(): Platform {
return this._platform;
}
public set platform(value: Platform) {
this._platform = value;
}
#ViewChild('content') nav: NavController; rootPage: any;
initialization: any; initializationApp: any; Platform: any;
statusBar: any; splashScreen: any; Storage: any;
constructor(public platform1: Platform, public StatusBar:
StatusBar, public SplashScreen: SplashScreen, private storage:
Storage) {
this.initializeApp();
}
initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
});
this.storage.get('session_storage').then((res) => {
if (res == null) {
this.rootPage = LoginPage;
} else {
this.rootPage = HomePage;
}
});
}
}
Please make sure your references to injected stuff inside constructor are the same as you call them in your methods. For example you have also name capital letters etc...
import { Component, ViewChild } from '#angular/core';
import { Platform, NavController } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { Storage } from '#ionic/Storage';
import { HomePage } from '../pages/home/home';
import { LoginPage } from '../pages/login/login';
import { RegisterPage } from '../pages/register/register';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
#ViewChild('content') nav: NavController;
rootPage: any;
initialization: any;
initializationApp: any;
constructor(public platform: Platform, public statusBar:
StatusBar, public splashScreen: SplashScreen, private storage:
Storage) {
this.initializeApp();
}
initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
});
this.storage.get('session_storage').then((res) => {
if (res == null) {
this.rootPage = LoginPage;
} else {
this.rootPage = HomePage;
}
});
}
}
you call platform while in your constructor you initialized platform1.
To fix update your constructor to point at "platform"

invalidpipeargument: '[object object']: error showing

So I am relatively new to Ionic and Firebase, and I am trying to display user data that already exists in Firebase.
Here is the error that I am getting:
invalidpipeargument: '[object object']: error showing.
I do know what the issue is after looking at other questions similar to mine. It seems I cannot assign the async function as database.object does not return an observable. So I have tried to add .valueChanges(); to make it an observable, but I believe this is clashing with the angularfireobject as that is already assigned to the variable profile.data so this would not work.
I have also tried this:
// get (): AngularFireObject<any[]>{
//return this.afDatabase.list`/profile/${data.uid}`;
//}
If you point me in the right direction that would be great.
Here is my code:
.ts file
import { Component } from '#angular/core';
import { NavController, ToastController } from 'ionic-angular';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFireDatabase, AngularFireObject} from 'angularfire2/database';
import { Profile } from '../../model/profile';
import { DEFAULT_INTERPOLATION_CONFIG } from '#angular/compiler';
#Component({
selector: 'page-about',
templateUrl: 'about.html'
})
export class AboutPage {
profileData: AngularFireObject<Profile>
// get (): AngularFireObject<any[]>{
//return this.afDatabase.list`/profile/${data.uid}`;
//}
constructor(private afAuth:AngularFireAuth, private afDatabase: AngularFireDatabase,
public navCtrl: NavController, private toast: ToastController) {
}
ionViewDidLoad() {
this.afAuth.authState.take(1).subscribe(data =>{
if (data && data.email && data.uid){
this.toast.create({
message: `Welcome to MatchMyFighter ${data.email}`,
duration: 3000,
}).present();
// this.profileData = this.afDatabase.object(`profile/${data.uid}`)
this.profileData = this.afDatabase.object(`/profile/${data.uid}`).valueChanges();;
}
else{
this.toast.create({
message:`could not autenticate`,
duration:3000
}).present;
}
})
}
}
.html
<p>
Username: {{(profileData | async)?.username}}
</p>
The call to valueChanges() converts the AngularFireObject<Profile> to an observable.
You have to change the type to Observable<Profile> like so:
profileData: Observable<Profile>;
constructor(private db: AngularFireDatabase) { } // other stuff emitted ...
ionViewDidLoad() {
// ...
this.profileData = this.db.object<Profile>(`/profile/${data.uid}`).valueChanges();
// ...
}

Get length of object in angularfire2 #askfirebase

Is there a way to use angularfire2 and get the length of an object?
Try this one:
import { FirebaseApp } from "angularfire2";
import { Inject } from "#angular/core";
export class AppComponent {
constructor(#Inject(FirebaseApp) fb: any) {
const ref = fb.database().ref();
ref.child('/lists')
.once('value')
.then(
(snapshot) => {
console.log(snapshot.numChildren()); // gets length
}
);
}
}
or
import { AngularFireDatabase } from "angularfire2";
export class AppComponent {
constructor(private afd: AngularFireDatabase) {
const lists = afd.object(`/lists`, { preserveSnapshot: true });
lists.subscribe(snapshot => {
console.log(snapshot.numChildren()); // gets length
});
}
}

Resources