EmberJS+Firebase Journey #4 — How to upload image to Firebase
Welcome to my 4th series on EmberJS+Firebase journey. In my last story, I walked you through on how to upload a csv file to populate a datatable, then push it to Firebase. Today we will take a quick look at how we can also do an image upload using the same component; Emberx-File-Input.
I have designed the hbs to look like this :

<div class=”form-group”>
<label class=”col-sm-2 control-label”>Image<br>(200x200)</label>
<div class=”col-sm-10">
<img id=’output’ height=”200" width=”200" hidden={{shouldHideImage}}>
<p></p>
{{x-file-input class=”custom-class” multiple=false name=”files” action=(action “didSelectImage”) accept=”image/*” alt=”Upload Image”}}
</div>
</div>
Here I I have set the <img> tag to have a dom id of ‘output’ so we can preview the uploaded image later with dimension of 200 by 200. Next we add a spacing in between and call the component “x-file-input”, disallow multiple files as for this case, I am only allowing single file upload. “files” is required by the component to store the file into an array. We then wire up the action method, I call it “didSelectImage”, to be triggered when user perform an upload. I set restriction to “png” so when user perform an upload, automatically “png” format is set.
After setting the look and feel, like wire them up in our controller ! Firstly, I will create some variables to ready up my firebase and file :
firebaseApp: Ember.inject.service(),
storageRef: ‘’,
file: ‘’,
With these variables setup, we will now create the action method “didSelectImage” :
didSelectImage(files){let reader = new FileReader();
// Ember.run.bind
reader.onloadend = run.bind(this, function(){
var dataURL = reader.result;
var output = document.getElementById(‘output’);
output.src = dataURL;
this.set(‘file’, files[0]);
});
//debugger;
reader.readAsDataURL(files[0]);
},
We have an input files from the file upload component we use as by default, the component takes in an array of files. Same as the previous csv upload, we instantiate a new FileReader, call onloadend (more info), once the upload is completed, we look for our element with id ‘output’, if you remember it was our <img>, so we load the data from our filereader to preview the image in <img>. Then, we set the image file from the first element of the files array to the variable ‘file’.

So here we achieved 2 things :
1. Storing our file into a local variable call ‘file’.
2. Get the image data and load it into our <img> tag.
Now that we have our file ready, let’s push it to our Firebase Storage! There are a few things we need to do to get it ready to be pushed :
1. Create the file metadata
2. Get Firebase Storage Reference
3. Create a path to the new file
// Create the file metadata
var metadata = {
contentType: ‘image/png’
};
var storageRef = this.get(‘firebaseApp’).storage().ref();
var path = ‘images/plans/’ + newPlan.get(‘id’) + ‘.png’;
Now we are ready to push it to firebase !

We will make use of the firebase storage api (UploadTask). First we create a task with our file and metadata.
var uploadTask = storageRef.child(path).put(this.get(‘file’), metadata);
Then, we use uploadTask.on and let firebase do the magic !
uploadTask.on(‘state_changed’, function(snapshot){
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log(‘Upload is ‘ + progress + ‘% done’);
console.log(snapshot.state);
}, function(error) {
}, function() {
var downloadURL = uploadTask.snapshot.downloadURL;
newPlan.set(‘imageUrl’, downloadURL);
newPlan.save().then(() => ctrl.transitionToRoute(‘plans’));
ctrl.set(‘file’, ‘’);
ctrl.set(‘selectedCategory’, ‘’);
ctrl.set(document.getElementById(‘output’).src, ‘’);
ctrl.set(‘days’, ‘’);
ctrl.set(‘isDisabled’, true);
});In here, we can actually get the amount of data transferred to update a progress bar and once it is done, we call “uploadTask.snapshot.downloadURL” to get the url to our uploaded image then we go ahead and push our newly created data model to firebase! And this is how it will look like in the console :

We can create folders to organize our images as the system scales, and I used the model’s id as the filename. If your model contains more than one images, its better to use other ways to generate your filename. Here is how the model looks like with the url :

So what have we done today? :
1. We prepared our view for image upload and image preview.
2. We wired our image uploader and previewer with our controller.
3. We hooked up firebase storage and pushed the image file.
4. We set the image url to our data model.
That’s it for now! If you have followed my EmberJS journey, by now you should have already know how to :
1. Setup an a dropdown with EmberJS+Firebase (#1 & #2)
2. Setup a file uploader with EmberJS+Firebase (#3)
Stay tune for more walkthroughs!