I have really been enjoying working with EmberJS lately, once you get over the learning curve and understand how things should relate, it becomes really fast and fun!
Lets take a look at how we can use Ember Data with Node (or io.js),Express and MongoDB. For this example lets use the Ember CLI to start an Ember application fast!
If you don’t have the Ember CLI installed make sure you install it via npm.
npm install -g ember-cli
Setting up the Ember Project
With this installed, navigate to the location you use to store your projects. Once you are in there we can start a new application, note that you do not need to create a new folder for this application since Ember CLI will do that for you.
ember new emberMongo
This command will start the process of creating a new ’emberMongo’ folder and Ember application for you. I have noticed some issues where the npm,bower install will not run. If you notice that the node_modules/bower_components folder is not there, simply run npm install
or bower install
.
Setting up Node Project
We will also need to setup our Node server. Let’s do this in a separate folder, since these are separate elements, one is the front-end, one is the back-end.
If you do not have MongoDB installed follow the MongoDB installation guide on the their website.
Create a new folder, and name it whatever you would like. In this case I am going to name mine ’emberServer’, once inside that folder we need to install a few npm modules.
First run npm init
to initialize a package.json file. Fill out the options as you require. Next we have to install the modules we will need.
npm install --save-dev express && npm install --save-dev mongoose
Here we install Express to handle our routing and Mongoose to handle interacting with our database.
Building the Sever
Inside your node project create a server.js
file and add the following.
var express = require('express');
var mongoose = require('mongoose');
var app = express();
mongoose.connect('mongodb://localhost/emberData');
Here we are getting Express and Mongoose and setting up our server with var app = express();
. We also tell Mongoose to connect to our MongoDB instance and look for a database called emberData, if no database exists it will create one for us! If you are unsure how to set up a MongoDB process check out Manage mongod Processes in the MongoDB documentation.
Before we get any further we will also want to make sure we set the appropriate headers for our server.
app.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
next();
});
In this case we want to allow the server that Ember CLI will create to access our content, which is http://localhost:4200
Creating our Mongoose Model
On our server first we need to create the model that we will use for our data. For the example of this post we will have some sort of notes application. So we will create a Note model.
With Mongoose we first need to create our schema for our model. The schema is the structure that will define our model, is the title a string? or is a value a number. In Mongoose this will look something like this:
var noteSchema = new mongoose.Schema({
title: 'string',
content: 'string',
author: 'string'
});
We use the schema to help define our model.
var NoteModel = mongoose.model('note',noteSchema);
Here we define our model, mongoose.model()
takes two arguments a name and a schema. As an aside when we insert documents into the MongoDB based on this model the collection it creates the pluralized version of the model name. So inside our emberData database there will be a notes collection.
Creating a route
To set up a route in Express, we can use one of the many HTTP methods, in this case we will just look at GET. To create a GET method we use the .get()
method from Express.
.get()
takes two arguments, the string for the path and a callback function that is passed the original request and a response stream. We will use that response stream to send our data, but first lets send a quick message to say that it works. We also need to add the line app.listen('4500')
after the route. This sets our server to listen on a specific port number, in this case 4500.
var express = require('express');
var mongoose = require('mongoose');
var app = express();
app.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
next();
});
mongoose.connect('mongodb://localhost/emberData');
var noteSchema = new mongoose.Schema({
title: 'string',
content: 'string',
author: 'string'
});
var NoteModel = mongoose.model('note',noteSchema);
//New lines!
app.get('/api/',function(req,res) {
res.send('Working');
});
app.listen('4500');
In order to test this in your terminal run node server
, this will run our server, if there are no errors you know it is running. In a new terminal window lets use the curl
command to test that our GET method is working.
curl http://localhost:4500/api
The response should be Working
. If this is working lets go ahead an create the route for getting all our notes.
app.get('/api/notes', function(req,res) {
NoteModel.find({},function(err,docs) {
if(err) {
res.send(err);
}
else {
res.send(docs);
}
});
});
Before we test this route we need to add some data to it! I have created a gist of some data HERE you can use. To do this the follow commands are what you will need to enter, this is assuming you have a mongo instance running.
mongo //Will open the mongo shell
use emberData //Will select the database we want
db.notes.insert(... paste in content from gist ...);
To test that that data is in there we can run db.notes.find()
. You should see the data we added as the output! If this is working we can now verify that our route is working, in the terminal we can now run curl http://localhost:4500/api/notes
.
Now that we have a working endpoint lets set it up so that we can get it to play nicely with how Ember Data expects the our API responses to be formatted.
app.get('/api/notes', function(req,res) {
NoteModel.find({},function(err,docs) {
if(err) {
res.send({error:err});
}
else {
res.send({note:docs});
}
});
});
We change the error response to be res.send({error:err});
and the success to be res.send({note:docs});
where note
is the name of the model we will create in Ember and docs
is an array of our returned documents. At this point we are ready to jump into our Ember project and start getting our data!
Jumping into Ember
Go back to your Ember project and in the terminal in that directory run ember serve
, this will start a server to run our ember application. Navigate to the url it provides you and you should see “Welcome to Ember.js”.
Much like we did in Mongoose, we need to define our Ember model. To do this using the Ember CLI we can run ember generate model note
this will generate the files we need for a new note model, it will place it in app/models/note.js
it will also create a test file for you! Open that file and and lets add our schema for how we want this model to be defined.
import DS from 'ember-data';
export default DS.Model.extend({
title: DS.attr('string'),
content: DS.attr('string'),
author: DS.attr('string')
});
In Ember Data we use the .attr()
method to define the type that our model will accept. Next we need to create a REST.adapter
to load and save our data. Using the Ember CLI lets generate a new adapter ember generate adapter application
. In the adapter file add the following.
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
namespace: 'api',
host: 'http://localhost:4500'
});
Here we provide information about our API in terms of the namespace and the host url. In order for this to work properly we need too set a property in our Ember config file. In config/environment.js
there is a variables called ENV
it will be an object. We need to add a new property where we can define what sources this site is allowed to interact with.
...
contentSecurityPolicy: {
'connect-src' : "'self' http://localhost:4500"
}
...
There is one last thing we need to do before we can actually get our data into our application, we need to create a serializers to convert the standard MongoDB _id
to id
. Using the Ember CLI let’s generate a new serializer, ember generate serializer application
. Inside the serializer we need to set what the primary key is and create a method to covert it.
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
primaryKey: '_id',
serializeId: function(id) {
return id.toString();
}
});
We are finally ready to display our data with Ember! To do so we need to create an application route, ember generate route application
. When we generate a new application route it will ask you if you want to replace the original application template, just say no. In here it is as simple as saying:
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.findAll('note');
}
});
this.store.findAll('note')
will make a GET request to the our serve at a http://localhost:4500/api/notes
. We can finally access our data in an Ember template! Inside templates/application.hbs
add the following lines.
{{#each model as |item|}}
{{item.content}}
{{/each}}
And that is it! If you go and check your site in the browser you will see your content showing up! I hope this helps get you started with using MongoDB with Express to build an Ember application! For more information check out the guide on the Ember site.
In the future look for an article on working model relationships!
Pingback: Using Ember CLI working with Fixture data - Ryan Christiani - Front-End Developer - Ryan Christiani – Front-End Developer()
Pingback: Using Ember CLI and working with Ember Data fixtures - Ryan Christiani – Front-End Developer()
Pingback: How to connect emberjs with mongodb - Quora()