Ember.js is an outstanding client-side framework for building single-page applications. To make your application truly come to life, Firebase, being a real-time backend, is a natural choice as the server-side component.
Sending data between the server and the client is a task all web applications have to address. However, if one uses the Firebase-Ember.js stack, this problem is largely abstracted away by these wonderful frameworks.
To make them work together, the Firebase team released their official Ember.js bindings, emberFire.
How does it work?
Before we look at the making of the actual application it is important to understand how the emberFire library works.
It is built on two primitives,
Ember.ArrayProxy, respectively. These proxy
objects delegate any
setProperty calls that are not defined on the
proxy to an underlying content object.
What this means is that we can work with Firebase references in our
application as if they were Ember objects. In the case of a single object,
setting a property will cause a child with that name to be written with the
passed value. When working with an array, the usual array methods (e.g
pushObject) can be used and they will do the right thing in the underlying
Firebase reference (e.g
push the new node).
Setting up the environment
To set up the necessary dependencies, it is easiest to download the latest Ember starter kit and add the following script tags to the main template:
1 2 3
With that in place, we can start developing. For the sake of focusing on one single issue at a time, the code snippets in this post do not always exactly match those in the actual application. If you want to see them in their entirety, you can always check the source code on Github.
The application we are going to build is an “Idealist”. Users can submit ideas and vote on existing ones.
When one loads the application it looks like the following:
A list of ideas is displayed along with the number of votes for that idea and a button to vote that idea up.
To get the existing ideas from Firebase, we use the
model hook of the
1 2 3 4 5 6 7 8 9 10
This loads the ideas in an
EmberFire.Array and then iterates through them in the
So how does adding a new idea happen? If we take a look at the
template, we can see that clicking on the “Send my idea” button triggers the
sendIdea action is then handled on the controller:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
We get a reference with a unique id by using Firebase’s push operation. We
EmberFire.Object with that reference and that enables us to do our
magic with the help of Firebase. When we then set any property on the object,
it is going to be persisted on our backend and synchronized to all clients.
Extending the EmberFire classes
Up until this point, we did not need to create our own model classes. The basic EmberFire classes were sufficient for our needs. However, if we need to define additional behavior for our models, we have to extend these primitives.
Suppose, for example, that each user has a certain number of votes and we want to prevent further voting when she does not have any votes left, as shown on the next mockup:
We can define a computed property on the user that would tell whether she has any votes left. Computed properties in Ember are properties that depend on other -computed or “normal”- properties and get automatically updated when one of the dependent properties change.
To do that, we need to define our User model:
1 2 3
The above is a computed macro definition that defines
noVotesLeft as true if
votesLeft property of the user is less than or equal to zero.
Then, in the template that renders each idea, we disable the button if that computed property is true and also give it a grey hue to indicate its disabled state:
Keep in mind that the context of the template is an idea and our computed
property is defined on the user, hence the need for
Wait, there is more
Taking things a step further, I have also integrated Firebase’s SimpleLogin authentication service and prevented the same user to vote on the same idea multiple times. If you wish to see how these are implemented, I encourage you to check out the source code of the project.
I hope I got you interested in learning more about how to build real-time web applications and gave you a basic example of how to use state-of-the-art tools to do so.