Linking providers to implement an image upload / data return from Firebase: Is this a valid example?

As mentioned in the title, I put together a process to load data into a component, as well as upload new images to Firebase and return the updated data. I’m wondering if my process is effective / good practice. Any feedback is welcome, thank you.

My component which displays images

import { Component } from '@angular/core';
import { NavController, NavParams, Slides } from 'ionic-angular';
import { CameraService } from '../../providers/camera-service';
import { FirebaseService, SingleImage } from '../../providers/firebase-service';

@Component({
  selector: 'page-image-page',
  templateUrl: 'image-page.html',
})

export class ImagePage {
publicImages: SingleImage[];

 constructor(private firebaseService: FirebaseService, private cameraService: CameraService,  public navCtrl: NavController, public navParams: NavParams) {
 }

 ionViewDidLoad() {
  this.publicImages = this.firebaseService.returnedPublicImages();
 }
  
 uploadNewImage() {
  this.cameraService.getCamera();
    this.publicImages = this.firebaseService.returnedPublicImages();
  }
}

My two services, One to get the image from phone’s photo library, another to interact with Firebase.

  1. Uploading from photo library
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/map';
import { Camera, CameraOptions } from '@ionic-native/camera';
import { FirebaseService } from '../providers/firebase-service';

@Injectable()
export class CameraService {

  constructor(private firebaseService: FirebaseService, private camera: Camera ) {
    }

  getCamera() {
    let options = {
      sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
      destinationType: this.camera.DestinationType.DATA_URL,
      encodingType: this.camera.EncodingType.JPEG,
      targetHeight: 1000,
      targetWidth: 1000
    }
    this.camera.getPicture(options).then((imageData) => {
       this.firebaseService.uploadImage(imageData)  
      })
    }
 }
  1. Service to interact with Firebase
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
import * as firebase from 'firebase'
import { AngularFireDatabase, FirebaseListObservable } from 'angularfire2/database';

export interface SingleImage {
title: string,
value: string
}

@Injectable()
export class FirebaseService {
images: FirebaseListObservable<SingleImage[]>;
publicImages: SingleImage[];

  constructor(private af: AngularFireDatabase, public http: Http) {
 }

    uploadImage(imageData) {
      let fbStorage = firebase.storage();
      let fbDatabase = firebase.database();
      let imagesList = fbStorage.ref('Images/');
      let imagesData = fbDatabase.ref('Images');
         let pic = {
             title: "",
             value: imageData 
            }
      let pushed = imagesData.push();
      let keyAndName = pushed.key;
      let storageChild = imagesList.child(keyAndName);
        storageChild.putString(imageData, 'base64', {contentType: 'image/jpeg'}).then((savedPicture) => {
           let urlVal = savedPicture.downloadURL;
           let picTitle = pic.title;
              pushed.set({
                     title: picTitle,
                     value: urlVal
                   })
                }).catch(err => alert('after putstring: ' + err))
    }

 returnedPublicImages() {
    this.publicImages = [];
       let returnMe = firebase.database().ref('Images');
         returnMe.orderByKey().on("child_added", (snapshot) => {
            this.publicImages.push(snapshot.val());
                })
                return this.publicImages
          }
 }

I use the same kind of thing in my app, the overall design is good, but I looked very fast.

Again looking very fast, something looks wrong with uploadImages() function. You lack of sequential conditions, remember that ionic works in parallel / async mode, you need to implement .then() conditions for that to work (especially to wait that the automatic id for the push be created on firebase realtime database, then try to upload the image with that id on the reference from the line before).

After your returnedPublicImages() function looks very good.

Hope it helps,

Happy coding with ionic :slight_smile:

Thank you @FrancoisIonic. I modified that function to include

 let pushed = imagesData.push().then((onStandBy) => {
      let keyAndName = onStandBy.key;
      let storageChild = imagesList.child(keyAndName);
        storageChild.putString(imageData, 'base64', {contentType: 'image/jpeg'}).then((savedPicture) => {
           let urlVal = savedPicture.downloadURL;
           let picTitle = pic.title;
              onStandBy.set({
                     title: picTitle,
                     value: urlVal,
                   })
                }).catch(err => alert('after putstring: ' + err))
              }).catch(err => alert('error with standby: ' + err))

Thank you for the piece of advice my friend!
Happy coding

@jaydz test it a bit on firebase database console (while you code and test, check on firebase database realtime console, the lag is around 1/2 s max if the record works), I hope it will work better now :slight_smile:

is working great with Firebase

perfect, have fun with ionic :smile: