Angularjs – A Hands On tutorial

Tweet about this on TwitterShare on LinkedIn0Share on Google+0Share on Reddit0Buffer this pageFlattr the authorEmail this to someonePrint this page

Angularjs – A Hands On tutorial

This is a hands on tutorial on Angularjs.  We will walk through most of the key features of Angular, and by the end we will build an Angular application named Movie Stub.

You can see the live demo of the app here.

Preview:

Screen Shot 2014-03-14 at 9.01.49 PM Screen Shot 2014-03-14 at 9.02.11 PM Screen Shot 2014-03-14 at 9.02.28 PM Screen Shot 2014-03-14 at 9.02.36 PMSo, lets get started.

Contents

Code for each topic is available here. And the complete application code can be found here.

Angularjs

What

AngularJS is a structural framework for dynamic web apps. It lets you use HTML as your template language and lets you extend HTML’s syntax to express your application’s components clearly and succinctly. Angular’s data binding and dependency injection eliminate much of the code you currently have to write. And it all happens within the browser, making it an ideal partner with any server technology.

Why

HTML is great for declaring static documents, but it falters when we try to use it for declaring dynamic views in web-applications. AngularJS lets you extend HTML vocabulary for your application. The resulting environment is extraordinarily expressive, readable, and quick to develop.

You can read more about the “W”s of Angularjs here.

Create an Angularjs Boilerplate [code]

To make this hands on session result in a more “re-usable” product, we will start off by creating a template. And in future if you want to create a new Angular project, you can reuse this template.

We are creating an Online Movie Ticket Booking website named movieStub. The architecture is pretty simple. We will have Nodejs & Expressjs as our server side components. Angularjs as our client side component along with Bootstrap for a pleasant UI.

Now, Create a new folder with the name movieStub. Next open Prompt/Terminal inside the movieStub folder. First we need to setup node, more details here. Next, We will init a new node project, run npm init. Hit return if you don’t want to fill any field (the default values will get applied). This will generate a package.json file, which should look something like

Even though this is a Angularjs tutorial, I thought it would not hurt anyone to learn a bit of server side. So, we will be using a Node server to server our static page. We are going to let express handle server side stuff for us. If you are not aware of express, you can check out this post & come back or else, you can copy paste the code from here to continue. To add express to our project, run npm install express --save-dev This will save express as a dev dependency to our project.

Next, we will setup bower. If you don’t have bower package manager already installed, you can install by running the following commands

Windows Mac/*nix
npm install -g bower    sudo npm install -g bower

Next, we will init a new bower file to track our dependencies. Run bower init You can do the same thing as npm init. And the final file should look something like

Lets install Angularjs & add it to our project. Run bower install angular --save-dev Next, we need to add Twitter Bootstrap to our project. Run bower install bootstrap --save-dev Next, create a new folder at the root and name it public.  Our folder structure should be like Screen Shot 2014-03-11 at 8.54.00 PM

  • Head to bower_components/bootstrap/dist and copy css,fonts & js folders to the public folder.
  • We will split our javascript files into 2 pieces. create a folder inside the js folder & name it lib.
  • Copy the contents of js folder inside the lib folder.
  • Copy angular.min.js from bower_components/angular to public/js/lib folder & jquery.min.js from  bower_components/jquery/dist to public/js/lib folder
  • Create a new file and name it index.html inside the public folder.

Our final structure will be like Screen Shot 2014-03-11 at 9.18.28 PM You can remove bootstrap.js inside the lib folder if you want. We will be referring only the minified file. Open index.html and we will set up reference to all the required resources. Copy paste the below to index.html

Do notice the data-ng-app=”” on line no 2. This is how we tell Angular to get started. There are other ways of writing the same like

<html ng-app="">  or  <html ng-app>

Its up to you. The way I wrote kind of gives a feel of completeness, again you can write it any way & Angular will work the same way.

Next create another file in the root of the movieStub folder & name it index.js. This will be our sever. Open index.js & paste the below code

That’s it!! Our basic template is done.

Back to Terminal/Prompt, run node index.js. This should start the server. Now navigate to   http://localhost:2595/ in your favorite browser & you should see our app name as heading and a sub heading. You can copy this folder structure as is and save it as a template and can use this for other projects. Now, lets dig into some Angularjs concepts.

Model Bindings [code]

Angular uses html markup as templates, and lets you define dynamic values with placeholders using the double curly braces notation {{ }}.  Angular tries to resolve the value inside the double curly braces, using a scope variable ($scope). To understand this, open index.html & add below highlighted lines

Check if the node server is running ( node index.js ) & refresh our home page  http://localhost:2595. You should see something like model_bindingAnd now, enter a movie name

model_binding_value

And bam!! The value of your favorite movie appears as you type in. So, lets analyse what all is going on.

  • Line 2  – Tells Angular to begin the magic.
  • Line 14 – We define a value (movieName) for ng-model attribute. This value will act as a variable storing the text box value. As soon as Angular see a variable inside the ng-model attribute, it will bind the variable to the $scope object & monitors for changes.
  • Line 15 – We use the movieName variable here. When the value gets updated, Angular notifies the changes to all the {{movieName}} & updates them. Also note the ng-show attribute. This tell Angular to show line 15 only when there is a valid value for movieName. 

PS: ng-model & ng-show are called as Angular directives. More on that in a moment.

Two_Way_Data_Binding

Here our template is the h1 tag, when compiled becomes our view and model is movieName.

You can read more about data bindings here.

Repeaters [code]

Repeaters are “for loops” for all you programmers. We define a list in the Angular scope & then iterate the list using a ng-repeat directive & display the data.

What are these directives you ask?

At a high level, directives are markers on a DOM element (such as an attribute, element name, or CSS class) that tell AngularJS’s HTML compiler ($compile) to attach a specified behavior to that DOM element or even transform the DOM element and its children.

More on directives here.

Now, lets create a new folder named controller inside public/js. This is where our controllers reside. Next create a new file and name it app.js.

A controllers is a JavaScript constructor function that is used to augment the Angular Scope. Remember the $scope object? This will set up the initial state of the $scope object.

Before that we will create a module & hook up the controller to it.

You can think of a module as a container for the different parts of your app – controllers, services, filters, directives, etc.

Copy the following code to controller/app.js

We create a new controller named movieStubController and append an array of movies to the $scope object.

Now, in our index.html, we will add a ng-repeat directive to iterate over the movies array and print the object. Before we do that, we need to tell Angular that our app scope is defined here. For that we update our ng-app directive to the name of the module. And then add a new ng-controller directive to the body tag. The updated index.html would be

On line 19, we are printing the id of the current movie, name & rating. This should give you an idea of the flow. If you refresh  http://localhost:2595/ page, you should see something like

Screen Shot 2014-03-13 at 9.19.12 AM

Filters [code]

Lets say that, we need to show all the movie names in uppercase. But we are not allowed to change the data source. This can be achieved via Angular Filters. Filters will take the raw data from model and performs action on it like converting the data to uppercase or lowercase or actually “filter” the data. Lets take a look.

Open your index.html & update line no: 19 from  {{movie.id}} - {{movie.name}} - {{movie.rating}} to  {{movie.id}} - {{movie.name | uppercase}} - {{movie.rating}}.

Back to our webpage & refresh, you should see all the movie names are in uppercase. To add a filter, we append a pipe (|) symbol next to the object/array/string you are trying to modify followed by the filter name. In this case a uppercase.

Now, lets print the list in “reverse alphabetical” order. For that replace line 18 from <li data-ng-repeat="movie in movies"> to  <li data-ng-repeat="movie in movies | orderBy:'name':true">, refresh the page and Bam!!

Do notice this time we are running the filter on the complete movies array. You can read more about orderBy here.

Another important filter is the json. This is very helpful when you are debugging. If you want to see what is inside your object, you can use this filter. Add the following line of code after the ending tag of ul on line 21  <pre>{{ movies | json }}</pre>  and refresh the page. You should see something like

Screen Shot 2014-03-12 at 9.38.25 AMNow, you know what exactly you are dealing with.

Using filters, we will let the user search for a movie from the list. Update your index.html as below

We are adding a text box on line no 21, which will act as a input source. Refresh the page, your output will be

Screen Shot 2014-03-11 at 11.13.23 PMThe logic is very similar to what we have done in modal bindings. The search model from the textbox is passed as input to the filter on line 26.  Also do notice that on line 26, we have 2 filters going on.

More about filters here.

Scope Functions [code]

Now, lets say that a user wants to know how many tickets are available for each movie. For this requirement, we will add a clickable link to every movie. Next when a user clicks on it, we will check our movies object against the clicked movie & show the availability. So lets get cracking.

First app.js, we will create a new function, that will take a movie id & return the movie object. So, here is the code for that

And we update our index.html as follows

Things to notice. Line 29 has a ng-click directive, which will call our getMovieById function. The argument to the function is the movie id. On line 33, Once the current movie variable is updated, we will show the availability for the clicked movie.

Save, refresh the page. Now when you click on the availability link next to each movie, you will see the availability value at the bottom of the list.

With the concept of scoping, we are for sure not polluting the global name space, Ensuring clean maintainable code.

In this way, we bind a function to a scope object & as long as the scope lives, we can access the method. Also do note that if we spawn any new scopes inside this controller (which we will a bit later on), the current scope will be inherited.

Partial Views [code]

Angular provides a simple way of implementing partial views. Components like headers & footers can be stored as templates & easily included in the page.

Lets create a new folder inside the public folder and name it tmpl. Inside that, create another file and name it header.html. Cut the below 2 lines of header from index.html

and paste it inside the newly created header.html. Now in index.html, in place of the above 2 lines, add

See the value of src? This is the path to the header source template. We will define this value inside our controller – app.js. Add the following line inside our movieStubController() 

And then refresh the page. You should not see any change. The page should load the same way. If you view source, the mark up will not reflect the header tags & if you inspect element via Firebug or Developer tools, the injected markup will appear.

Routers [code]

Moving to the awesome parts of Angular, we will take a look at Routers. In this part, we will integrate the concepts we have learned so far.

Lets say that a user wants to see the complete details of the movie when he clicks on it, not below the list but in a new “View” altogether. We would leverage Angular’s Route Provider.

To work with routers, we need to include an Angular extra named angular-route.min.js. Navigate to Angularjs downloads & click on the download link. Bottom left hand corner of the popup, you will see a link named extras. Click on it. In the next page, look for angular-route.min.js. Download and save it to public/js/lib.

Next, we will create a new folder named router inside public/js folder & create a new file named router.js. Copy the below code to router.js

In this file, we have added our routes to which we will respond with a new view. If the URL is the root URL or home URL, we load the home.html partial If the route is /movie and a movie id, we redirect to movie.html (which, we will create now) & trigger the movieDetailsController. If we are not aware of the current URL, we will redirect to home route.

Next, Create a new file inside tmpl folder and call it home.html. We will abstract all the content from the index.html into this file, so that we can switch views easily. You will understand what I mean in a moment. Copy the below contents to home.html

Next create another file and name it as movie.html and add the below code

And your index.html should be updated to

Notice that we have added a new div on line 19. This is our place holder for all our pages. Depending on the page URL, Angular will fetch the corresponding view & fill this tag. We have added the reference to angular-route.min.js & router.js too.

Now finally, the updated controllers/app.js

Do note that we have added a new dependency to our module ngRoute. Next, we have also added 1 new function to the scope named back(), this is for navigating back to the previous view. And a new controller, that will populate the current movie object from the id in the URL.

All this will get cleared up in a moment. Save all the files and refresh our home page http://localhost:2595/. Do notice the url  http://localhost:2595/#/. Anything after the #/, Angular will look for in the routes we have configured. Your home page should be like

home-routeYou can click on review & you should be redirected to a new view, like

Screen Shot 2014-03-14 at 10.31.52 AM

Click on the back link and you should be taken to the movies list page. Play around for a while, have a look at the code again till you connect the ends of each layer. If you are still confused about something do drop a note.

Housekeeping [code]

Now we have a basic structure going on. I have cleaned up the UI to make it more of a movie site. First create a new file and name app.css inside public/css. And then update the following files

public/css/app.css

public/index.html

public/tmpl/header.html

public/tmpl/home.html

public/tmpl/movie.html

public/js/controller/app.js

Save all the files and refresh the page. You should see something like this

Screen Shot 2014-03-12 at 9.42.32 PM Screen Shot 2014-03-12 at 9.42.48 PMLooks a lot better doesn’t it?

Services [code]

Angular services are substitutable objects that are wired together using dependency injection (DI). You can use services to organize and share code across your app.

Angular services are:

  • Lazily instantiated – Angular only instantiates a service when an application component depends on it.
  • Singletons – Each component dependent on a service gets a reference to the single instance generated by the service factory.

As part of this tutorial, we will have a sample data file on the server. When we hit a certain end point, the server will dispatch this data as response.

We need to download another Angular extra named angular.resource.min.js. Navigate to Angularjs downloads & click on the download link. Bottom left hand corner of the popup, you will see a link named extras. Click on it. In the next page, look for angular.resource.min.jsDownload and save it to public/js/lib.

Next, lets create a new folder name data at the root (/movieStub). Inside this create a new file and name it movies.json. Copy & paste the below json object.

Next, we will update our server index.js, so that when we hit the end point /movies, it will dispatch this data. Update the index.js to

Create a new folder & name it service. Inside this, create a new file & name it services.js. We will define our factory here.

You can read more about Factory & Services here.

Update the services.js with the below code

Update index.html to refer the newly created js file by adding this line at the end of all script tags in the head   <script type="text/javascript" src="js/service/services.js"></script> &  <script type="text/javascript" src="js/lib/angular-resource.min.js"></script> after the angular-route.min.js file.

Update app.js as

Save all the files, stop the server & restart it by running node index.js (since we have updated our index.js) & you should see that the data loads up from the json file! And you page should look something like

Screen Shot 2014-03-14 at 11.14.53 AM

 

All the data is now coming from the server! And as you have seen, the process is pretty simple.

Posting Data – Book Tickets [code]

We have showed all the movies we are airing. Now lets provide the user an option to book tickets. For this, we will add a new partial view. Inside public/tmpl/ create a new file named bookTickets.html. Add the below contents

In this page, we are showing the summary of the movie the user clicked to book tickets for. The we give him an option to add the quantity and select the date.

Do notice the ng-disabled attribute on line 25, on the submit button. If the validation fails, we are disabling the submit button. And ng-pattern is a very powerful utility when dealing with inputs. We can write a regular expression in the pattern and  we can check the validation using formName.formField.$valid value. This will be false when the validation fails. Which we are leveraging to show an error message as well as disable the submit button.

Next, lets update the router.js with the new route. Updated public/router/router.js

Next, we will update our controller and add functionality for the post. Add the following code to controller/app.js

Do notice the onlyNumbers regular expression is defined here. Next, we are creating a placeholder object named formData. We will use this to map the values from form, so that we can send the data to the server as a single object.

Along with the tickets quantity & date, we need to store the movie id & movie name for display purposes.

We are creating a processForm() to send the data to server. This is very much similar to jQuery Ajax.

Next, we need a server side endpoint to update the booking details. Lets add that code to index.js. Copy the below code and replace the index.js code.

We have added the app.post().

Lets say that, a user is on the movie details page and s/he wants to book a ticket. For that lets add a book button to public/tmpl/movie.html. Updated movie.html.

And, lets enable the book button only when we have an availability. Lets update tmpl/home.html. Replace <a href="#" class="btn btn-success " role="button ">Book »</a>  to  <a data-ng-href="#/bookTickets/{{movie.id}}" class="btn btn-success " role="button" data-ng-disabled="movie.availability == 0">Book »</a>.

If you save the files and run the app, you can book tickets. Click on a Book button & you will be shown a new view to book tickets. Enter the quantity & date. Click on submit. Now open your console to see the response logged

Screen Shot 2014-03-14 at 8.34.01 PM

 

Simple right! Now lets build a view to show all the bookings.

Fetch Data – Show Booking Details [code]

For that, we will define a new route open router/router.js & update with the following

Next, we will add a service endpoint on the client side. This will be similar to the movies. But this will return the list of bookings made. Open service/services.js and add the below code

And a new controller to fetch the details

Do notice the isActive() & isActivePath() methods on line nos. 28 & 32. we will use them in a moment in the header to toggle menu active status.

Next, lets add the actual view bookings.html. Inside the tmpl folder create a new file named bookings.html & add the below code.

We will also update the header.html as below

Next, the heart of the logic. The server. Update the index.js with the below code

Save all the files, restart the server and Bam!! You should see a new tab named Bookings & if you book the tickets, it will redirect you to this page with the booking details.

Screen Shot 2014-03-14 at 8.51.18 PM

 

Thats it!! Our App is completed.

Hopefull this app will help you as a guideline to make more awesome SPA apps with Angularjs.


Thanks for reading! Do comment.

@arvindr21

 

 

Tweet about this on TwitterShare on LinkedIn0Share on Google+0Share on Reddit0Buffer this pageFlattr the authorEmail this to someonePrint this page
  • Soief Ali

    Arvind, I think you forget to mention that we need to install git from https://git-for-windows.github.io/, as because I am gettin error (Bower: ENOGIT Git is not installed or not in the PATH) when I am trying to install angular or bootstrap (bower install angular –save-dev, bower install bootstrap–save-dev).

  • Jag

    Wow. This is great hands-on on AngularJS. Just for future readers, I came across this wonderful resource for Angularjs tutorial directly from TechCBT here: https://www.youtube.com/playlist?list=PLvZkOAgBYrsS_ugyamsNpCgLSmtIXZGiz

  • rohitth

    i am not able to resolve this error can any one help

  • joe

    HI all, can anyone help? i got this error after i have followed all steps and run “index.js”:

    throw new Error(‘Most middleware (like ‘ + name + ‘) is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.’);

    i have try to install it myself using:

    npm install connect”

    but it didn’t help, i still can not run the server

  • atejeda

    On the routing example, that part of the line is missed:

  • llimpeo

    Create an Angularjs Boilerplate
    I fail to generate the run index.js node; In your example runs successfully from github.

    ===my bower.json ====
    “dependencies”: {
    “angular”: “~1.4.6″,
    “bootstrap”: “~3.3.5″
    }

    ==my package.json==

    “dependencies”: {
    “express”: “^4.13.3″
    }

    ===the error.=====
    [email protected] /c/nodework/movieStub
    node index.js
    :nodeworkmovieStubnode_modulesexpresslibexpress.js:99
    throw new Error(‘Most middleware (like ‘ + name + ‘) is no longer bundle
    ^
    Error: Most middleware (like logger) is no longer bundled with Express and must be installed separately. Please see htt://github.com/senchalabs/connect#middleware.
    at Function.Object.defineProperty.get (c:nodeworkmovieStubnode_modulesexpresslibexpress.js:99:13)
    at Object. (c:nodeworkmovieStubindex.js:6:16)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
    at node.js:814:3

    Why ..? i’m new in node & angular…

    • llimpeo

      var bodyParser = require(‘body-parser’);
      var morgan = require(‘morgan’);

      var app=express();

      //app.use(express.logger()); old version
      app.use(morgan(‘combined’));

      //app.use(express.json()); old version
      app.use(bodyParser.json());

      //app.use(express.urlencoded()); old version
      app.use(bodyParser.urlencoded({extended : true}));

  • Ash

    hi,

    I have one question i m using ng-grid and i have on button on button click I want to convert grid header to textbox and user enter value and save coldefs update any idea how can i achieve this.

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Hello Ash, I have not worked explicitly with ng-grid but I think after you update the col-defs, you may need to destroy and re-create the table. You can give that a try.

  • Vikrant

    Hi Aravind, great tutorial. I m stuck at the last part, I get an error – ReferenceError: $ is not defined. It is complaining about this part:

    data: $.param($scope.formData).

    Does it have to do something with using the latest version of angular?

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Hey Vikranth. Thanks!

      $.param() is from jQuery, to serialize an object to string. More info : http://api.jquery.com/jquery.param

      Can you pls. check your jQuery version?

      Thanks.

      • Vikrant

        Hey Arvind,

        Changed the jquery library to the latest one and everything fell into place. App works great. Thanks a lot.

        • http://thejackalofjavascript.com/ Arvind Ravulavaru

          Great! Glad it worked out. Thanks for sharing.

  • Randy Davis

    Arvind, I’m having trouble with the index.html file on line 29 in the Scope section. Nothing happens when I click on the “Availability” link when the link tag is as follows:

    Availability

    Since I’m fairly new to all of these, I can’t tell if it’s an express issue or what and I can’t seem to find anything that shows this except examples that call a function after “javascript:myFunction()” as the href value. Any ideas?

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Hello Randy, I don’t think it is an Express issue. Can you compare your code with the Github code : https://github.com/arvindr21/ngMovieStub/tree/master/tutorial-parts/part-7_Routers and see if you can find the difference. Thanks.

      • Randy Davis

        Ok, I worked through part 7 and figured it just wasn’t showing up due to there not being routes for it in step 5. Also, in step 7 the code for the actual “Review” link is missing in the article code for home.html but it’s in the code you told posted on github. Thanks Arvind!

        • http://thejackalofjavascript.com/ Arvind Ravulavaru

          Cool! The new post should be a lot better :) Thanks for sharing.

    • http://caffeine.shugendo.org David “Lefty” Schlesinger

      Yeah, this fixed it for me as well. Well done, Randy, thanks.

  • Randy Davis

    Just figured out how to get it running to use Express 4:
    – npm install morgan (takes place of logger)
    -npm install body-parser (takes care of json and urlencoded)

    Add the following lines to your variables at the top of index.js:
    -bodyParser = require(‘body-parser’),
    -morgan = require(‘morgan’);

    var app should be changed to look like so:

    var app = express();
    app.use(morgan(‘combined’));
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded());

    ….

    This did the trick for me, but note that you will get a body-parser deprecated message in the terminal after trying it again but at least the app works in the browser now and no more error messages!

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Thanks for sharing Randy. I am planning to rewrite this article to use the latest Angular and Express.

    • Panayiotis

      Thank you for your solution :)

    • Soief Ali

      Thanks, its helpful

  • EasyPlease

    Can you update this tutorial to use Express 4…. can’t get it to work

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Sure will take that as a request. Will let you know once done.

    • Randy Davis

      See my post from last night to see if it helps

  • Steven Ndaye

    My man, you are great. This was an awesome tutorial. The best I have seen so far when it comes to SPA. Keep it up.

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Thanks Steven

  • Md Sajjadul Farooque Robin

    It’s really a very good angular tutorial in simple way. Keep it up.

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Thanks Robin!

  • Jim

    Hi,
    Amazing write up. I am very very new to JS / Web (transitioning from the WIN32 world – a desktop dev). Why do we need to set up “express server”. I thought AngularJS is all about client side coding i.e. it will run on any modern browser. Sorry for my naive-ness.

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Hello Jim. Thanks!

      Yes, express is a server side framework. One of the beautiful features of Angularjs is its REST integration, so I wanted to showcase that as well from a getting started perspective. I thought that Once you are aware on how to build an application on the client side with Angular, as well as integrate with a server side REST service, it would make this post more Hands on-ish!

      Hope that made sense. Thanks!

  • Vishveshwara Vasa

    Very good and detailed article on AngularJS. Good Job!!

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Thanks Vasa.

  • acveer

    Aravind,

    Thank you for suggesting slush-express. I did try & it was very easy to set up & get started with view engine, but I wanted to use ‘.html’ instead of ‘.ejs’ for the above tutorial. It all worked out great in the end.

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Great! Thanks!

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      @acveer:disqus Added html support to slush-express. You can check that out next time.

  • acveer

    My sincere appreciation for such a well written AngularJS tutorial. I am able to implement it end to end and thoroughly enjoyed it. It covered all main components like modules, route, services, factory, views and their significance.

    I was using express 4.X and using ‘EJS’ to render html, so I have to refer new libraries and change the config (a little) to display HTML & dependent JS/CSS from ‘public’ folder.
    var path = require(‘path’);
    var bodyParser = require(‘body-parser’);
    var logger = require(‘morgan’);

    app.engine(‘html’, require(‘ejs’).renderFile);
    app.set(‘view engine’, ‘ejs’);
    app.set(‘views’, __dirname + ‘/public’);
    app.use(express.static(path.join(__dirname, ‘public’))); //to serve CSS & JS

    The tutorial has a few gotchas (that can be figured out easily), which are perfect in my opinion to look back & learn how it all fits together.

    Thank you for being such an awesome contributor.

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Thanks for the Kind words acveer.

      Yup, I think, I am aware of the gotcha’s :). Thanks for adding the Express 4 server code. Really appreciate it.

      Thanks,
      Arvind.

  • acveer

    Excellent tutorial Aravind. I am trying to follow it and I am currently stuck at showiing the basic template. I am using Express 4.X, so I changed index.js accordingly with ‘morgan’, ‘body-parser’ and has the server up, but unable to display ‘html’, getting error “Cannot find module html ” when accessing localhost:2595.

    From some suggestions online, installed ‘ejs’ and added this ‘app.engine(‘html’, require(‘ejs’).renderFile);’, but this is expecting the index.html under /public/views folder. If we move it under views, then we need to move all other css, js, fonts under the same directory.

    Could you please suggest how we can display the basic template with express 4.x ?
    Below is what I currently have for index.js, which works but only with index.html under ‘/public/views’ folder.

    var express = require(“express”),
    fs = require(‘fs’),
    port = process.env.PORT || 2595;

    var bodyParser = require(‘body-parser’);
    var logger = require(‘morgan’);
    var favicon = require(‘static-favicon’);
    var app = express();

    app.use(favicon());
    app.use(logger(‘dev’));
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded());
    app.set(“view options”, {
    layout: false
    });

    //view setup
    //app.set(‘views’, path.join(__dirname, ‘views’));
    app.use(express.static(__dirname + ‘/public’));
    // used below code to render html files
    app.engine(‘html’, require(‘ejs’).renderFile);

    //routes
    app.get(‘/’, function (req, res) {
    res.render(‘index.html’);
    });

    app.listen(port);
    console.log(‘Express server running at http://localhost:’ + port);

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Thanks acveer. From now on, you can https://www.npmjs.org/package/slush-express to scaffold Express 4 apps. Its simple, select the view engine (ejs) and stylesheet engine (css) and bam! Your Express 4 app is ready.

      Do give it a try and let me know if any issues.

      Thanks,
      Arvind.