Firebase CRUD operations with JavaScript and jQuery

Learn how to do Read and Write Data operations on Firebase Realtime Database i.e. Firebase CRUD operations with JavaScript and jQuery.

Firebase CRUD operations with JavaScript and jQuery

In this tutorial we are going to learn how to do data operations on Firebase i.e. CRUD operations in Firebase with JavaScript and jQuery.

This tutorial is a follow up to the tutorial Auth Schemes in Google Firebase and Custom Router for Firebase jQuery App.

To understand Firebase CRUD operations, we will have the Movie as our entity which is being added, viewed, updated or removed.


Router

As our custom router is going to load the template, and fill it with data in following way:

var Auth = require('./auth');
var Router = require('./router');

//Redirect to some Page or URL
var redirect = function(to) {
  appRouter.go(to)
}

var appRouter = new Router({
  mountPoint: '#root',
  indexRoute: 'index',
  routes: {
    login : {
      path: 'login',
      templateUrl: 'partials/login.html',
      onEnter: function() {
        var user = Auth.checkLoggedInUser();
        if( !user && window.location.hash.match('/login') ){
          return true;
        } else {
          return 'index';
        }
      },
      controller: require('./controllers/login')(Auth, redirect)
    }
  }
});

Here in above code, you can see the controller key for a particular route. Which grabs the module and executes it with its dependencies i.e. Auth and redirect.


Add and Update

Add Data

So To Add the data, following method from Firebase API can be used:

var key = firebase.database().ref().child('movies').push(data).key;

In the above code we are getting the reference of DB from firebase.database().ref(). And then going to the movies node by .child(‘movies’) where we are going to save the new data.

And then pushing it to the node by .push(data). This saves the data to Firebase and returns the newly created object reference.

So the .key attribute after push will give the key with which new data has been saved.

Now for out application, we want to save same data in two different locations/endpoints simultaneously. So we are going to follow the Update approach to add the new data.

In this first we push the empty data to generate a new empty node with key. And then do update operations on the key itself.

Following code demonstrates that.

var Key = firebase.database().ref().child('movies').push().key;

// Write the new post's data simultaneously in the movies list and the user's movie list.
var updates = {};
updates['/movies/' + Key] = movie;
updates['/user-movies/' + uid + '/' + Key] = movie;

return firebase.database().ref().update(updates);

Here we have created an associative array with all the updates that we wanna perform. So for two paths, same data is going to be saved.


Update Data

This updates array can be passed to the update method on the Firebase DB reference as firebase.database().ref().update(updates).

In our example, it will be done in three steps

  1. Load the Data
  2. Fill The Data
  3. After edits, on clicking save, Save the data on same reference

First and Third step will utilize the key that they receive from the router. Following code demonstrates that:

//See complete file at 
//https://github.com/time2hack/movie-db/blob/master/src/js/controllers/edit.js
var query = firebase.database().ref("movies/"+params.id);

//Fire Query
query.once("value").then(fillData)

//Fill The form data
function fillData(snap) {
  var data = snap.val();
  console.log(data)
  $('#movieName').val(data.movieName);
  $('#releaseYear').val(data.releaseYear);
  $('#generes').val((data.generes || []).join(', '))
  $('#duration').val(data.duration);
  $('#directors').val((data.directors || []).join(', '))
  $('#actors').val((data.actors || []).join(', '))
  $('#imdbUrl').val(data.imdbUrl);
}

//Save function (similar to Adding the data. 
//This time we don't generate new key but utilize the one received from Router parameter
function saveMovie(movie) {
  var uid = firebase.auth().currentUser.uid;
  var postKey = params.id; //Params is received from the Router
  var updates = {};
  updates['/movies/' + postKey] = movie;
  updates['/user-movies/' + uid + '/' + postKey] = movie;

  return database.ref().update(updates);
}

Read

To list and view the data, we just need to execute the query. And the Firebase DB reference is query by itself. So on creating the reference and then attaching the event handler will let us read and render the results.

Following code queries and passes to the render function for single item.

var query = firebase.database().ref("movies").limitToFirst(20);
query.once("value")
  .then(function(snapshot) {
    snapshot.forEach(renderSingleSnapshot);
  }).then(function(){
    $(document).find('#list').html(markup);
  });

var renderSingleSnapshot = function(singleSnapshot){
  // ... code to render
}

The data received from Firebase is called snapshot. The snapshot has few methods and iterators with it. Those can be used to retrieve values and keys from snapshot or loop over the data.

var firebase = require('firebase');
var $ = require('jquery');
var durationConvertor = require('../utils/duration');

var ListController = function() {
  return function () {
    var userId = firebase.auth().currentUser.uid;

    // Get a reference to the database service
    var markup = '';
    var database = firebase.database();
    var query = firebase.database().ref("movies").orderByChild('createdAt').limitToLast(20);
    query.once("value")
      .then(function(snapshot) {
        snapshot.forEach(renderSingleSnapshot);
      }).then(function(){
        $(document).find('#list').html(markup);
      });

    var renderSingleSnapshot = function(movieRef) {
      var movie = movieRef.val();
      console.log(movieRef.key, movie);

      var imdb = '';
      var editLink = '';
      var html = '';
      if(movie.uid === userId) {
        editLink = ` <a href="#/edit/${movieRef.key}+"><i class="fa fa-pencil" aria-hidden="true"></i></a>`;
      }
      viewLink = `<a href="#/view/${movieRef.key}">${movie.movieName}</a>`
      if( movie.imdbUrl !== '' ){
        imdb += ` <a href="${movie.imdbUrl}" target="_blank"><i class="fa fa-imdb" aria-hidden="true"></i></a>`;
      }

      html += `
        <li class="list-group-item media movie">
          <div class="media-body">
            <h5 class="media-heading">${viewLink}${imdb}${editLink}</h5>
            <h6><b>Director: </b>${movie.directors.join(', ')}</h6>
            <small><b>Released in: </b>${(movie.releaseYear)}<br/>
            <b>Duration: </b>${durationConvertor(movie.duration)}<br/>
            <b>Actors: </b>
            <small>${(movie.actors || movie.stars).join(', ')}</small>
          </div>
          <div class="media-right">
            <img class="media-object" height="125" src="${movie.poster}" alt="${movie.movieName}" />
          </div>
        </li>`;

      //Add new ones on top
      markup = html + markup;
    }
  }
}

ListController.toggleStar = function(movieUniqueId){
  console.log(movieUniqueId);
}

module.exports = ListController;

Remove

Removing the data is also not a hassle, though we are not implementing it in out MovieDB application for now.

Following code shows that remove() method can be used to remove the and key reference:

firebase.database().ref("movies").child(key).remove();

So creating a function and calling it with event handler will look like that. Though the button to trigger the delete event must have the data-key attribute. And the value of this attribute is the key which needs to be removed.

var remove = function(e){
  e.preventDefault();
  e.stopPropogation();
  var key = $(this).data('key');
  if(confirm('Are you sure?')){
    firebase.database().ref("movies").child(key).remove();
  }
}
$(document).on('click', '.btn-remove-key', remove);

Hence the above code will be functional for the buttons and links created like this:

<button type="button" class="btn-remove-key" data-key="-dsdsf-sample-key">Delete</button>
<a ref="#" class="btn-remove-key" data-key="-dsdsf-sample-key">Delete</a>
<span class="btn-remove-key" data-key="-dsdsf-sample-key">Delete</span>

So in this way, you can perform Firebase CRUD Operations. Please let us know about your views about the article in comments.


Conclusion

Let me know through comments ? or on Twitter at @heypankaj_ and/or @time2hack

If you find this article helpful, please share it with others ?

Subscribe to the blog to receive new posts right to your inbox.

Hey There! You have made it this far.

Would you like to subscribe via email?