Getting Started With EmberJS
Filed under: Ember.js, JavaScript, web development
comments (57) Views: 51,790
JavaScript heavy applications can be found all over the place these days. As JavaScript applications become more and more complex, it's no longer acceptable to have a long chain of jQuery callback statements, or even distinct functions called at various points through your app. JavaScript developers are slowly learning what traditional software programmers have known for decades. Organization and efficiency are important and can make the difference between an app that performs great, versus one that doesn't. So a number of JavaScript MVC frameworks like Backbone, Knockout, and Ember have sprung up to fill the void between beginner and intermediate developers, and hardcode programmers. They offer various features and functionality and will each of them will suit different people based on their needs.
I consider myself a pretty good developer...by no means the best, but I'm skilled at taking existing technologies and forging them into something unique and of my own creation. I've been eyeing these frameworks for a while now and for my needs it's come down to Backbone, and Ember. I've done research on Backbone, even purchasing a Backbone video tutorial. It's nice, but still seems hard to wrap my head around. I started hearing about Ember just a few months ago, and already it's gaining traction. It offers many features that appeal to me and so I decided to dive in and see how it fits me. Ember offers several key pieces of functionality that I find very appealing, chief of which is data binding. This simply means that you can create a variable, then tell Ember that when that variable changes, update any part of your application which watches that variable. Think a stock ticker, real time chat, etc.
One of the drawbacks of Ember over Backbone is that the latter has a wealth of tutorials, articles, and Github projects while the former has very little available material. What IS out there tends to give a very shallow coverage of the basics, then dive straight in to the in depth stuff, the parts that only people who've been using it for a while understand. So it's my goal to write a bare bones, basic Ember tutorial that will cover the parts that many people tend to leave out. I'm also writing this article to help cement my own understanding of these concepts.
Ember.js is an MVC (or Model View Controller) style framework which simply means that it offers you the ability to break out your code into 3 distinct types of pieces.
- M = Model - The Model is like a cookie jar. It's where your data is stored while waiting to be used by the app.
- V = View - The View is the visual aspect of your app. It's a form your users interact with to input information, it's a list of data they can select from, etc.
- C = Controller - Think of the Controller as the traffic cop. It manages the interactions between the other parts of your application. When someone clicks a button, the Controller decides what View should be loaded, which in turn determines what Model is used to populate the information.
Let's get started shall we? First things first, go ahead and download the Ember.js starter kit. Unzip it and dump it into a directory that's web accessible. Open index.html and js/app.js in the text editor of your choice. Within app.js, add the following line.
Congratulations! You just created your first Ember application! Load index.html in your browser and glory in the website you just created. Oh wait, there's nothing there...what do you think this is? Ruby on Rails? Nothing shows up, except for the title, and that's perfectly fine. All that's going on is that behind the scenes Ember has created an application for you that you'll reference throughout the rest of the tutorial. You may see other developers refer to the Application as a Namespace. This simply means that all the other parts of your app will start with the name you selected. This helps avoid variable collisions and keeps everything neat and tidy.
One thing that most jQuery developers are used to is our old faithful document.ready block. Ember offers something similar by passing in an optional object to the create method. Add the code below, reload your page and you should get an congratulatory alert. Pat yourself on the back...you deserve it.
The next thing we need to do is to add our data, or Model. Each Ember application can have multiple Models, each "Modeling" a unique type of data. In some languages a Model is the same thing as a class. It's basically a blueprint for how to refer to this object. Let's create a model for some of my favorite books.
The next thing we need is a Controller. In addition to controlling traffic, Controllers in Ember also funnel data to the View from the Model. Here's a simple Ember Controller.
Implicit in the creation of an Ember ArrayController is a content array. This is where the information about our books will be stored. It's there, you just can't see it. If you want to though, you can explicitly create the content array, perhaps you wish to prepopulate it. That's accomplished by passing an optional object to the create method, just like we did with the Application.
Now that we have a Model and a Controller, we need a View. Remember that the View is the part users will see, so that's going to be part of the HTML file so switch over to index.html. Let's add our view, then discuss it. Directly below the H1 tag, add the following code.
One of the great things about Ember is that it ships with a built in templating engine called Handlebars, in fact templates are a key piece of Ember's magic. In general templates work by wrapping the variable pieces of your code with some string. With Handlebars it's a curly brace, and not just one, but two of them. Turn your head sideways and you'll see why they call them Handlebars pard'ner.
Ember started it's life as a library called SproutCore, developed by Apple as the "core" of it's online applications like Mobile Me. SproutCore also included UI widgets which Ember does not...sort of. Ember has built-in views for form elements because those can be highly dynamic. In the case of our template, or View, we're using an Ember button. This allows Ember to do all of the grunt work for us. It takes a target, our bookController, and an action. So when someone clicks the button, it will run the loadBooks function of the Welcome.bookController. See how it all fits together?
The second chunk is a little more complicated, but I know you'll get it. Your mother always said you just needed to apply yourself. In Ember, a collection is simply a pointer to a grouping of data, in our case it's the Welcome.bookController object again. I mentioned that data binding is one of the reasons I'm interested in Ember, and we can see it's power here. Content simply points to the content variable in our bookController, while the Binding portion of it is the magic dust. Adding Binding to the end of most attributes tells Ember that you want to initiate a two way binding. Change the information on one side and the other will update. Lastly the collection allows you set a base tag, in our case it's a plain bulleted list.
By the way, the # and / symbols are merely there to tell Handlebars that this particular View has a closing part.
Inside the collection is the meat of our template. Notice how we're mixing HTML tags right in the middle of our template. Nice eh? Another nicety that Ember offers is that we don't have to explicitly add the opening, or closing, list item tags. It appears to add it automatically because it knows we're using a bulleted list. Running the app now and you should see a lonely button who needs friends. Clicking the button would make him unhappy because at the moment there is no "loadBooks" method. How about we add that...and some data while we're at it.
Remember when we said that Models can contain arbitrary functions? Well everything in Ember can contain custom code, including ArrayControllers. Let's add the loadBooks function, as you see it above. Now, when you load your page, and click the "Load Books" button you application should jump into action and load in the list of some of my favorite books. You care, I know you do. That's about it for this simple example. I hope you enjoyed it, and will consider giving Ember a try. You can download the complete source code on Github.
Wait, wait, wait. If you're like me you've got questions. Lots of questions. I wrote this blog post because I had questions that took me hours to find the answers to. In fact, most of the questions I had, I answered in this post. If you've questions that haven't yet been answered feel free to post them here. If I don't know the answer (which is likely), I'll find out and reply.
Make sure to check out my much longer and more in-depth article on Ember.js over at Adobe's Devnet.
If this article was interesting, or helpful, or even wrong, please consider leaving a comment, or buying something from my wishlist. It's appreciated!
Hey Andy,
Great post. Looking forward to more. I'm glad you are sharing your learning processes with the rest of us. And I want to help in that process by offering you some corrections in your terminology use. Specifically around your use of the term "model".
In your post you refer to your Books object as "a model" and that "In some languages a Model is the same thing as a class...". But this is not how I teach it.
According to MSDN: "The model manages the behavior and data of the application domain, responds to requests for information about its state (usually from the view), and responds to instructions to change state (usually from the controller)."
So the model is a collection of classes (or in the case of JavaScript a collection of objects), not necessarily just a class by itself. In the case of your example you *do* only have one class in your model, but if you added additional class (CD, DVDs, MediaLibrary, etc), they would still all be part of the same "Model", they would not each be a model by themselves. They are *model objects* that are all part of the same model. I hope that makes sense.
Also, the model is more than just a data container. Some models (anemic ones) do sometimes only provide that functionality. but a more robust data model can contain much more. Specifically, a domain model contains the business logic for the problem domain and the behavior that goes along with that business logic in addition to the data.
There is certainly more to go into about the Domain Model, but this is just a blog comment, so I will refer you to a pretty good article on it from MSDN (Geez, I am an MS fanboy today). http://msdn.microsoft.com/en-us/magazine/ee236415.aspx
Oh, and one more thing. You called your model object "Books", but when you think about it, when created each instance of that model object will represent a single Book. So a better name for that object would be "Book".
Jason Dean - March 08, 2012 08:36 am
Great little intro. Thx!
Khanh - March 08, 2012 08:57 am
Thanks for the intro. I'm missing the connection between the model and the controller. How does the controller know about the model? Naming convention?
Alan Humphrey - March 08, 2012 09:35 am
Alan...
That's a great question, and it turns out that there IS no connection. In fact if you completely delete the creation of Welcome.Books the app will in fact run just fine.
Going back and reviewing my code, you don't need a Model in this simple example because we're pushing the data straight to the page.
I'll need to study this further but for now it appears that you don't need the Model to run the code.
Oops.
andy matthews - March 08, 2012 12:51 pm
Nice tutorial, more please!
Eishay Smith - March 13, 2012 04:13 pm
Thank you Eishay...I'll be publishing a more in depth tutorial soon over at the Adobe Developer Connection. Look for it next month.
andy matthews - March 13, 2012 07:36 pm
For those of you that have been curious about Emberjs.com's lack of documentation, I discovered a hidden gem:
http://ember-docs.herokuapp.com/
I'm not sure why they don't link the API docs on the actual Emberjs.com website but there's the docs. They were generated just a few days ago so they seem like they're current.
andy matthews - March 14, 2012 09:06 am
Great kickstart for those exploring EmberJS.
So I am looking to use EmberJS as part of a web app and I'm looking for UI widgets to connect to it. Does it make sense to use jQuery UI and jQuery Mobile for that?
What are people using to get a slick set of widgets on top of Ember?
Charlie Woloszynski - March 22, 2012 03:38 pm
Charlie...
I just asked that question on Stack Overflow actually:
Because Ember just provides a blank canvas I think you could use anything you wanted. I'd wager that some are using Twitter Bootstrap.
andy matthews - March 22, 2012 09:52 pm
Glad to see more posts and discussion about Ember.js, I've been following it for a while as well but have yet to use it.
I have used JavaScriptMVC (javascriptmvc.com) which has been great. The one thing it hasn't had is data binding, but that's coming in the next month or so (when they release v3.3).
Also check out CanJS which is going to be the new "internals" behind JavaScriptMVC, pretty impressive stuff!
It's been around a while and includes stuff to get you testing and documenting your code early.
Anyways, thanks for the posts and I look forward to following your blog.
Craig - April 14, 2012 04:23 pm
Nice article !
Just two remarks :
- the model should probably be called Welcome.Book and the controller Welcome.booksController as the model is a blueprint for a book, and the controller is some kind of collection of books
- i had to replace $get by $getJSON to make it works, without that, the JSON data seem to be treated like a string !
Eric - April 18, 2012 04:57 pm
Wouldn't it be better to write loadBooks like :
loadBooks: function(){
var self = this;
$.getJSON('data/books.json', function(data) {
data.forEach(function(item){
self.pushObject(Welcome.Books.create(item));
});
});
}
This way, you create Welcome.Books object and not simple object.
Eric - April 18, 2012 09:19 pm
Thanks for your suggestions Eric. I've updated the code to reflect them.
andy matthews - April 19, 2012 09:53 am
Andy, I noticed you said above that Ember does not require jQuery. When I tried Ember just now - and simply loaded the file into a document (didn't actually do any 'Ember' type things), I got an error. Turns out you have to load jQuery first. This isn't documented anywhere on the Ember.js home page.
Raymond Camden - May 06, 2012 01:50 pm
No it's not. I realized that after I wrote this article. Updating now.
andy matthews - May 07, 2012 09:09 am
Hi Andy. I'm not seeing any of your Gist code embeds in this page. All of the external JS references ( tags I assume) have been replaced with . I understand this is a XSS attack protection feature of some web stacks. Any ideas? (I'm on Chrome 18 OSX.)
Thanks. I'm looking forward to working through your example!
Adam Block - May 15, 2012 09:49 am
Adam...
Thanks for letting me know. I've repaired the Gists and verified that they're showing.
By the way, I have a much more in-depth article on Ember.js that I wrote for Adobe. It just released today, you should check that out too:
http://goo.gl/vOgyf
andy matthews - May 15, 2012 10:45 am
Andy, thank you for taking the time to write the tutorials. We are evaluating several MV* frameworks to make a formal recommendation. I'm down to a top 3, Ember, CanJS and Backbone in that order. Your articles have helped with this process tremendously!
UpWorks - May 16, 2012 03:52 pm
Glad to help UpWorks. I haven't used CanJS and I've used Backbone a little. Ember kicks though...it's awesome.
andy matthews - May 17, 2012 10:08 pm
Hey Andy,
thanks so much for this tutorial and the winecollection app,
I'm already very familiar with Backbone and I'm writing a paper for my studies about the differences with Ember, you made this a lot easier,
Thanks mate
Thorwald Lambrecht - May 28, 2012 09:13 am
Thorwald...
Make sure you check out the article I wrote for Adobe on Ember.js. It's much more in depth.
http://goo.gl/vOgyf
andy matthews - May 28, 2012 06:45 pm
Great article once again! Thanks for the tip!
By the way both (this and wineapp) of your examples work for me in firefox, but they do not seem to work for me in Chrome.
Thorwald Lambrecht - May 30, 2012 11:14 am
Thorwald...
I downloaded the "Starter Kit" then added each piece from above one by one. At the end it works just fine in Chrome.
One thing that I did find in testing was that some servers don't have a JSON mime-type set up. Could be that your server is one of those?
I uploaded my copy of this article for you to review. The only difference is that I'm loading books.txt instead of books.json.
The wineshop app might be the same problem.
andy matthews - May 30, 2012 03:00 pm
Thanks for the write up. It seems like the "{{#view Ember.Button... }}" method has been deprecated with the latest ember.js build. I've included the following working code to replace it with though.
<button {{action "loadBooks" target="Welcome.booksController"}}>Load Books</button>
I look forward to reading more about ember.js!
Shun - May 31, 2012 12:52 am
Thanks Shun...
I'm actually working on updating some of this content for the newest release. This is perfect.
andy matthews - May 31, 2012 06:16 am
Such a brillant introduction to Ember, I'm looking forward to getting my hands on it more and more
Chris - June 01, 2012 04:13 pm
Great introduction to Ember, it looks pretty straightforward with the MVC model. Please keep going with such a great work.
Daniel - June 12, 2012 10:27 am
lovely, you only need to fall under the magic of CoffeeScript and your life will change.
c - June 12, 2012 12:42 pm
@c...hah! I'm slowly adopting tools like Rails, Ember, Grunt, etc...not sure if I'll ever be enticed into using CoffeeScript.
andy matthews - June 12, 2012 02:10 pm
why did you choose emberjs and not backbone?
mhmgrouop - June 12, 2012 02:36 pm
Nice writing. One question though, if data changes server side, is it going to update the html view too? Thanks.
Ewerton - June 12, 2012 04:06 pm
Hi Matthews, your link to "longer and more in-depth article on Ember.js" is broken and needs a "http://"
Tianshuo Hu - June 12, 2012 08:40 pm
@mhmgroup...I tried Backbone, even buying a video tutorial from Joey Beninghove but it just never made sense to me. When I started looking at Ember, something just clicked. Hard to explain but Ember just makes sense.
@Ewerton...at the moment Ember doesn't have data syncronization built in like Backbone does, but there is an official plugin for it called Ember Data. I suspect it will be rolled into the Ember core prior in time for a 1.0 release.
@Tianshuo Hu...thank you! Fixed.
andy matthews - June 12, 2012 08:50 pm
I rally fail to see how this adds anything to the docs out there. Was expecting more.
recroad - June 12, 2012 10:44 pm
@recroad...It doesn't add much to the docs that are out now, but I wrote this article in March when the documentation was very poor. In fact it wasn't even linked on the Ember.js website.
I'm sorry that you feel let down, did you take a look at the MUCH more in-depth article I wrote for Adobe?
andy matthews - June 12, 2012 10:51 pm
Awesome, thank you. We're getting into Ember and this is very useful
Brian Cardarella - June 12, 2012 11:58 pm
I have to say that you gave me the initial kick to take a look at Ember in more depth. Great article.
Jakub Arnold - June 16, 2012 09:40 am
Thanks Jakub...glad you enjoyed it.
andy matthews - June 17, 2012 06:03 am
Just found Ember.js today and so glad I found your tutorial in the beginning. Not many people can teach this good.
Thanks
devin - June 23, 2012 08:01 am
Andy,
I discovered Ember.js last summer (2011). My background has been in ActionScript 3 and frameworks such as Robotlegs. It looked very promising then but lack of documentation and online resources just killed all my desires to learn EmberJS. StackOverFlow was there but just couldn't get all the answers to my questions. I was downright frustrated, and had developed this unholy hatred towards "TODO". After reading your encounters with EmberJS, I feel so much better now, knowing that I wasn't the only one out there. I am gonna give it another go, now that the online documentation and website has been sorted out. I thank you for your time and efforts on this.
Xane - July 01, 2012 01:00 am
Xane...that's great to know...and in fact what I was shooting for. Programming shouldn't automatically be easy, but it also shouldn't be harder than it needs to be. Glad the article made you take a second look at Ember.
andy matthews - July 01, 2012 06:57 am
Thanks for this tutorial!!! .....just one note. I don't believe that your alert reads 'you did it!' and not "Hello World" The coding gods weep in their sleep. hehe!
sirBertly - July 02, 2012 07:57 am
Hey Andy,
tank you for this post. I'm new with Ember and your posts are really useful. I have a question for you because I didn't found information about the sintax that you have used at this line:
{{#view Ember.Button target="Welcome.booksController" action="loadBooks"}}
In particular, where can I find docs about Ember.Button sintax?
I found some like this
{{#view tagName="button" ...
what are the differences?
I'm Davide from Italy (Milan)... GRAZIE ;-)
Davide - July 03, 2012 04:30 pm
I'm sorry I see only now that Shun have already done my same question...
tks! ;-)
Davide - July 03, 2012 04:36 pm
Why aren't collections part of models but put in controllers? Collections often contain domain knowledge (=model).
Poul - October 15, 2012 04:19 pm
Good question Poul, that would be one for the Ember team, not I. Plus many things have changed in Ember since I published this article. Go check out the new Ember docs website.
andy matthews - October 25, 2012 11:57 am
nice work !
walid - October 29, 2012 07:15 am
Very nice Andy. Heading over to the "verbose" version next.
Originally, I was following along and the button click was doing absolutely nothing. I thought, "This stuff doesn't work...". Well, Chrome apparently is having issues with jQuery when trying to open the data file just as Thorwald mentioned. FireFox seems to work just fine.
Also, I tried to upgrade this example to the latest version of EmberJS and the button never even showed up. Thoughts?
Thanks and you've got a great writing style!
Wil Bloodworth - October 29, 2012 08:06 pm
Yes. Chrome can't open local files using the file:// syntax. If you're in a Mac you can easily open a simple Python web server in your current directory by using this shell function.
https://github.com/commadelimited/Getting-Started-With-Ember/issues/1#issuecomment-6986941
andy matthews - November 01, 2012 07:41 am
Thanks for the tutorial. Very helpful!
Kevin McInturff - November 10, 2012 07:40 am
Thanks for the kind words Kevin. Appreciated.
andy matthews - November 10, 2012 08:50 pm
Andy, many thanks for such a well written and thought out piece. I to have been struggling with these types of frameworks lately as although I have some experience with event based jQuery apps using Pub/Sub etc, the way these frameworks structure things has been confusing to say the least.
Finally your article / video and the in-depth piece on adobe's website with the tweets app really helped my understanding to move forward with Ember.js
In particular these 4 lines made such a massive difference to my understanding :
"A user performs an action such as typing on the keyboard or clicking a mouse button.
The Controller receives that input and fires off a message to the Model.
The Model changes its content based on the message (deletes a row or updates shopping cart quantities).
The View watches for a change in the Model and updates the user interface accordingly."
sums it brilliantly!
I am now an avid subscriber of your material and look forward to learning a lot more from you!
many thanks,
John
John Beadle - November 14, 2012 07:48 am
John. Thanks so much for the kind words. Just what I needed to read this morning.
andy matthews - November 19, 2012 08:30 am
Hi Andy, looks like some of the code snippets are missing. E.g. "gistfile1.js" seems to be missing. A great tutorial though.
--Christiaan
Christiaan Prins - December 29, 2012 06:04 pm
Thank you for a tutorial for people just diving in - we are always forgotten by those who are well down the MVC/Moustache rabbit hole. I have written a number of standard data-and-the-DOM-are-almost-one type apps, so have a clue like you, but was lost getting off the ground. Much obliged. Now, on to your Adobe article...
Erik - January 23, 2013 03:37 pm
Hi Andy,
Any chance of an updated tutorial with the new versions of Ember and Handlebars? I've updated to new jQuery, new Ember and new Handlebars...now it doesn't work using the depreciated Ember button or with a jQuery click event (Welcome.booksController.loadBooks();) , both of which work with the older version of Ember. I'd be soooo very obliged if you could update the example and such.
Erik
Erik - January 23, 2013 04:23 pm
Erik...
I'm actually working on a 3 part article on Ember.js for NetMag. Look for part one to release in a few weeks. If you follow me on Twitter you can make sure not to miss the announcement.
Thanks for your kind words and I'm really glad you got something out of the article.
andy matthews - January 23, 2013 07:00 pm