This sprint we will:
- focus on Read
- connect our partially pre-built front-end to a back-end with hard-coded data.
- replace the hard-coded data with data stored in a mongo db
Now would be a great time to explore the files provided for you. In particular note:
- the html in views/index.html
- the incomplete server in server.js
- the included package.json
Use nodemon
or node server.js
throughout the exercise to run your server.
Continually verify that your browser console is displaying the app.js loaded!
message on document-ready.
Goal display hard-coded data from app.js
on index.html
Let's start on the outside and work our way in.
-
Open
index.html
and find the HTML for an album. Convert this into a handlebars template by adding the correct script tags. Make sure you remove the data and place appropriate attribute placeholders in place instead. (You can get those attributes from the array of objects provided inapp.js
) Leavediv.albums
in place. -
Open
app.js
and edit the functionrenderAlbum
to display one Album on the page. Use the handlebars template. -
Run the function on document-ready and give it
sampleAlbums[0]
(just one album). Verify that the page looks right.
hint: calling renderAlbum
$(document).ready(function() {
console.log('app.js loaded!');
renderAlbum(sampleAlbums[0]);
});
- Update your code to use all the sampleAlbums. Create a
sampleAlbums.forEach
in your document-ready - use this to callrenderAlbum
for each album.
Note that we could use the templates
#each
method and pass it all the albums at once. However, we're planning to be able to add individual albums later on, so we'll need the ability to render each album individually. Having two separate render functions and templates (1 for individual albums, 1 for all albums) seems excessive at this point.
At this point you should see all 4 hard-coded albums rendered on page.
Rendering all the albums with handlebars
$(document).ready(function() {
console.log('app.js loaded!');
$.get('/api/albums').success(function (albums) {
albums.forEach(function(album) {
renderAlbum(album);
});
});
});
// this function takes a single album and renders it to the page
function renderAlbum(album) {
console.log('rendering album', album);
var albumHtml = $('#album-template').html();
var albumsTemplate = Handlebars.compile(albumHtml);
var html = albumsTemplate(album);
$('#albums').prepend(html);
}
We're going to add the following index route on our server:
GET /api/albums
To better organize this app we're going to be using controllers to separate out logic for different resources
. That means that when you create a route like /api/albums/:id
you'll put the server code to handle that in a separate file; and reference it's function. See also: Big explanation about controllers and the module pattern!. If you take a look in server.js
you'll see that we've already required the controllers for you.
-
Open server.js and create a new route for
/api/albums
. This route's callback should point tocontrollers.albums.index
. -
Open
controllers/albumsController.js
and fill in the index function to return all albums. -
Serve the hard-coded albums in
albumsController.js
on/api/albums
. This is an API route, so let's send JSON. -
In
app.js
, useajax
to get the albums. Render them on the page. -
You can safely delete the hard-coded data in
app.js
now!
The data in
albumsController.js
andapp.js
is different; making it easy to see which data is being rendered on your page.
Let's setup the database now.
-
Use
npm
to installmongoose
. -
In
models/album.js
add a model for our albums. You should be able to determine the datatypes based on the sample data we've been using. -
Export Album in
models/album.js
-
Require and export Album in
models/index.js
hint: `models/albums.js`
//models/album.js
var AlbumSchema = new Schema({
artistName: String,
name: String,
releaseDate: String,
genres: [ String ]
});
var Album = mongoose.model('Album', AlbumSchema);
module.exports = Album;
hint: `models/index.js`
module.exports.Album = require("./album.js");
Let's try seeding our database.
-
Move the hard-coded model data from
server.js
intoseed.js
. You'll note there's already an empty variable there for you to use. -
Strip out the pre-coded
_id
properties, mongo will take of creating these for us. -
Make sure
mongod
is running in a terminal. -
Run node seed.js
-
Resolve any errors you encounter.
hint: `error connect ECONNREFUSED`
If you see an error like:process.nextTick(function() { throw err; })
^
Error: connect ECONNREFUSED 127.0.0.1:27017
It usually means that mongod
is not running.
Now that the database is seeded, let's continue and use it in our /api/albums
route.
-
Delete the hard-coded server data.
-
Require
./models
incontrollers/albumsController.js
. -
Edit the current
function index
to access the database and pull all albums. -
Verify that you're getting the right data on your index page now. Your ajax should still work; but if the
keys
in the data have changed at all you'll have to resolve that.
hint: requiring `./models`
var db = require('./models');
If you're stuck, take a look at the solutions branch
If you've made it this far then we've created an API that has an index route /api/albums
.
Our app has a single-page view that makes an ajax GET request to the API and renders the information. Our data is being Read from the database by the server.
We've completed the Read component of our CRUD app for the moment.
Good job!