Create your blog with Angularjs From Scratch

In this tutorial you will learn how to build a blog with angularjs from scratch . our home page will consist of a fully functional carousel, hero unit, and three content sections with call to actions. The following screenshot is that of the home page

Let’s get started with the creation of our application. We’ll start by performing the following steps:

  • Create a folder named hl, short for “dunebook blog”.
  • Assuming that you have already installed Yeoman, open up the terminal. Let’s create the scaffolding for our app using the following lines of code:
    mkdir hl
    cd hl
    yo angular 

    Note

    Generator-Angular must be installed before you can run your Angular app. In case you haven’t installed it during Tutorial , Setting Up Your Rig, please install it using the following command:

    sudo npm install –g generator-angular
  • In the prompt, press Y for the question, Would you like to include Twitter Bootstrap?.
  • For the question, Would you like to use Sass (with Compass)?, press N.
  • For the third question, press Enter to accept the default settings.

    Quick Tip for You

    Using a CSS preprocessor such as SASS or LESS is always a good practice as it allows you to use variables and mixins in CSS, ensuring that your CSS remains modular and follows DRY (Don’t Repeat Yourself) principals. However, covering them is beyond the scope of this book.

    You should be seeing npm pulling a bunch of files and creating the scaffold of your app. Wait patiently until it is all done and you are returned back to the command prompt.

    You should now be able to see the structure of your application with the default home page.
    As we are going to be using UI-Bootstrap, let’s install it using Bower.

  • Fire the following command in the terminal:
    bower install angular-bootstrap

    This will create the angular-bootstrap folder within the app/bower_components folder.

    To be able to use Angular Bootstrap in our application, we need to include the JS file.

  • Let’s open up the app/index.html file and add the following highlighted line.
    <script src="bower_components/jquery/dist/jquery.js"></script>
    <script src="bower_components/angular/angular.js"></script>
    <script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>

    If you look into the bower_components/angular-bootstrap folder, you’ll notice there are the following two types of files along with their minified versions:

    • ui-bootstrap.js: This contains all the directives, but it doesn’t contain any templates. It makes sense to use this file if you do not want to use the default templates but want to customize your templates from scratch.
    • ui-bootstrap-tpls.js: This contains all the directives along with the default twitter bootstrap template code. If you are not looking to make any customization, then its best to include this file in your project.
  • Adding the ui.bootstrap dependency

    The next step is to add the Angular Bootstrap dependency to the Angular app.

    We do this by modifying the following line in the app/scripts/app.js file:

    angular.module('hlApp', ['ui.bootstrap'])

    Now, angular-bootstrap will be available for use across our application.

    Creating the navigation bar

    To create the navigation bar, let’s open up the app/index.html file and add the <nav> part of the code, which is shown as follows:

    <nav class="navbar navbar-default navbar-fixed-top">
        <div class="container">
            <a class="navbar-brand" href="/">dunebook blog</a> 
    
            <ul class="nav navbar-nav">
                <li> <a href="/#/articles">Articles</a>
                </li>
                <li> <a href="/#/gallery">Gallery</a>
                </li>
                <li> <a href="/#/subscribers">Subscribers</a>
                </li>
    
            </ul>
        </div>
    </nav>
     <!-- Add your site or application content here -->
        <div class="container" ng-view=""></div>

    As you can see from the preceding code, we defined the header tag and applied the CSS classes, navbar and navbar-fixed-top, to it. These are predefined bootstrap CSS classes that are used to style the navigation bar.

    The navbar class is a default container that sets the overflow to visible for all elements within the navbar DOM.

    The navbar-fixed-top class will make the navigation bar stick to the top of the page, and it will stay fixed even as the page scrolls. You can also use navbar-fixed-bottom to make your navigation bar stick to the bottom of the page.

    Now, we’ll add the <div> tag with a class named container. The container class will set the width of this element to 940 px and also center the element horizontally on the page.

    We will add our dunebook blog website within an anchor tag and give it a class named navbar-brand, as this is what our brand name is supposed to be.

    Navigation links for the Articles, Gallery, and Subscribers pages will be added as hyperlinks within an unordered list, which is styled using the nav class. Note the ‘/#/‘ in the href values.

    Save the file and start the server using the following command:

    grunt serve

    This will run the serve task defined within our Gruntfile.js file. You should now be able to see the navigation bar at the top of the page.

    Adding the carousel

    Now, let’s see how to add a carousel using angular-bootstrap. I’m sure most of you would have added carousels in your project. Most probably, these would have been one of those numerous jQuery plugins, and I’m sure that some of you must have struggled to make it work the first time.

    Angular Bootstrap has its own custom directive for carousel and it’s extremely easy to add a carousel to your home page using it.

    As the home page is rendered using the MainCtrl controller and the views/main.html partial, we will be adding our carousel code to these files.

    In the past, one of the biggest drawbacks of creating HTMLized click flows has been the intermingling of design and data. Most designers would create regular HTML pages with static markups linked with each other. The problem with this is, besides a lot of repetitive code, when these click flows are taken up to create the actual app, there is a fair amount of rework that would need to be done.

    Now, with Angular, it becomes extremely easy to separate your presentation layer from the actual data. Besides making this very efficient to write, it also becomes very easy to take this for actual development, as one now needs to only replace the static data models with the dynamic data; the presentation layers don’t need to be changed at all.

    With the idea of keeping the data separate from the markup, let’s first create our data models in the app/scripts/controllers/main.js file.

    We will delete the current awesomeThings model and start replacing it with the following code:

    var baseURL='http://lorempixel.com/960/450/';
    $scope.setInterval=5000;

    Now, when you create any kind of website or mockup, there is always a need to use placeholder images or stock images. There is an excellent site called www.lorempixel.com that provides images of the desired dimensions and for a certain category.

    It is extremely easy to use lorempixel where you want to display placeholder images. For example, use http://lorempixel.com/960/450/sports, where 960 and 450 are the width and height, respectively, of the desired image, and the category is sports. Visit www.lorempixel.com to see the list of category keywords they support.

    As we are going to be using images from here, we’ll define a variable named baseURL with the URL string passing the width and height parameters that we want for the image.

    Next, we create another variable called setInterval with a value of 5000. This will be used to set the autoslider of the carousel to 5 seconds.

    Now, we’ll create our slides model using the following lines of code:

    $scope.slides = [
       {
             title:'7 Ways to stay Fit',
             image:baseURL+'sports/',
             text:'Play a sport for 30 minutes a day!'
       },
       {
             title:'Healthly Food',
             image:baseURL+'food/',
             text:'Food that you should be eating!'
       },
       {
             title:'Relaxing Holidays',
             image:baseURL+'nature/',
             text:'10 Locations for Nature Lovers!'
       }
    
        ];

    This is essentially a JavaScript object with three parameters, namely title, image, and text. Note that for the image property, we prefix the term baseURL to the category name for each of the slides. This completes our work on the model.

    Now, let’s first open the views/main.html file and add the following markup above the jumbotron element:

    <carousel interval="setInterval">
       <slide ng-repeat="slide in slides" active="slide.active">
       </slide>
    </carousel>

    As you can see, this is a custom directive called <carousel> that has been natively written in angular-bootstrap.

    The interval attribute is used to set a delay between each slide change as follows:

    interval=setInterval

    We then loop though the slides using ng-repeat.

    Now, we’ll put in the elements that will display the image, title, and text. Within the <slides> tag, add the following code:

          <img class="carousel-image" ng-src="{{slide.image}}"/>
          <div class="carousel-caption">
                <h2>{{slide.title}}</h2>
                <p>{{slide.text}}</p>
          </div>

    Save the files and watch the browser refresh automatically (this happens if you have the server still running).

    You should now be able to see the slider working.

    You’ll notice that the navigation bar is overlapping the carousel. This is because of the position:absolute property that gets applied when we add the navbar-top-fixed class.

    You’ll also notice that on wide-screen monitors, the carousel image doesn’t cover the entire width. This happens because by default, Bootstrap works in the responsive mode and will change the container width to 1170 px while our carousel image is 960 px.

    To fix these problems, we’ll add the following CSS classes. In the app/styles/main.css file, delete the present code and add the following lines of code:

    body{
      padding-top: 50px;
    }
    
    .carousel-image{
      width: 100%;
    }
    
    
    
    

    Tweaking the hero unit

    OK. Now, let’s clean up our hero unit and put in some decent text. Let’s open the app/views/main.html file and change the content within the hero unit element as follows:

    <div class="hero-unit">
      <h1>Welcome to dunebook blog</h1>
      <p>This is a Rapid Prototype demo on how you can use angularjs with Angular UI and Bootstrap to quickly build a clickable prototype that can be shown to clients</p>
    </div>

    You’ll notice that the hero unit is quite narrow and feels claustrophobic; we can make it look nicer by adding the following class in the styles/main.css file.

    .hero-unit {
        font-size: 18px;
        font-weight: 200;
        line-height: 30px;
        background-color: #eee;
        border-radius: 6px;
        padding: 60px;
    }

    Adding the three content blocks



    Things are taking shape! Let’s now add the three blocks under the hero unit. We will use the same approach of keeping the data within the model and the markup in the partial.

    Open up the app/scripts/controllers/main.js, and let’s create another model named content, as we want to use images from lorempixel there too. We will follow the same structure for the content model as we did for the slides model.

    Add the following code for the content model just after the slides model:

    // Model for the 3 content blocks
    var baseURL='http://lorempixel.com/200/200/'
    $scope.content=[
    {
       img:baseURL+'people',
       title:'About Us',
       summary:'We are good, we are the best out there'
    },
    {
       img:baseURL+'business',
       title:'Our Services',
       summary:'We offer advice on staying Healthly, what to eat...
       what are the best exercises for you etc.'
    },
    {
    
       img:baseURL+'transport',
       title:'Contact Us',
       summary:'#111, Good Health Blvd, Happy Place, Antartica, Zip-432167'
    }
    ]

    Here, we are using 200 x 200 px size images from lorempixel.com.

    The structure of the model object is very similar to that of slides, so understanding this should be easy.

    Now, let’s add the markup in our app/views/main.html partial.

    After the hero unit markup, let’s create the row container that will contain the following <div> tags for the three blocks:

    <div class="row-fluid">
    
    </div>

    To create the three blocks, we’ll need three containers, and each of them would be four columns wide.

    Note

    As the default Bootstrap is 12 columns wide, the width for each of the three columns is simply 12 / 3 = 4.

    Within the row-fluid class, let’s create the markup for one of the blocks which we will repeat using ng-repeat. The code is as follows:

       <div class="col-md-4" ng-repeat="block in content">
             <img ng-src="{{block.img}}">
             <h3>{{block.title}}</h3>
             <p>{{block.summary}} </p>
       </div>

    Save the file and load the page on your browser to see the changes take effect.

    Things look OK, but those square images within the blocks don’t look that great; maybe we should put them within circles.

    With Bootstrap, it’s just a question of adding the img-circle class to the <img> tag as follows:

    <img class="img-circle" ng-src="{{block.img}}">

    Save the file and ensure that the images within the three blocks are now in a circle. In case you want the images with a rounded corner or with a polaroid effect, then simply replace the img-circle class with img-rounded or img-polaroid.

    This completes the home page.

    Creating a new view

    Ideally, I’d call it a page, but as what we are building is a single-page app, we don’t technically have different pages. What we do have are views, wherein a view is nothing but a unique URL or route that is linked to a controller and its corresponding partial.

    To create a new articles view/page using Yeoman, we simply need to run the following subgenerator command in the terminal:

    yo angular:route articles
    



    You’ll now notice that Yeoman has automatically performed the following set of actions:

    • Created a new controller named articles.js within app/scripts/controllers
    • Created a new partial named articles.html within app/views/
    • Created the files for unit tests within test/spec/controllers/articles.js
    • Modified the app/scripts/app.js file and added it in the routes for the articles view

    Now, isn’t that a lot of manual work you have been saved from!

    To know more about the list of generators and subgenerators available on your system, use the following command line:

    yo –help
    

    Yeoman also allows you to create your own generators. The following link gives out more information on how to create or extend a generator:

    http://yeoman.io/authoring/

    Understanding routes

    Routes play a very important role in your angularjs app. The routes essentially tell angularjs what controller and view to use for the given browser URL.

    In our application, the routes are stored in the app/scripts/app.js file.

    Routes make use of $routeProvider, and each route has two parameters: the first parameter is the path and the second is an object parameter. The following lines of code are entered under $routeProvider:

        $routeProvider
          .when('/', {
            templateUrl: 'views/main.html',
            controller: 'MainCtrl'
          })

    The when part defines the URL in the browser address bar. The templateURL part points to the partial that would be called within the ng-view directive. The controller part defines the controller function that will bind this view.

    In angularjs, the views and controllers are loosely coupled. What this means is that controllers and views are independent of each other, and it is in the routes file that a controller is linked to the view. So, essentially, you could have two different views bound to a single controller. This improves code reusability.



    After the completion of this Tutorial, your routes would look something like the following.

    'use strict';
    
    angular.module('hlApp', ['ui.bootstrap','ngGrid'])
      .config(function ($routeProvider) {
        $routeProvider
          .when('/', {
            templateUrl: 'views/main.html',
            controller: 'MainCtrl'
          })
          .when('/articles', {
            templateUrl: 'views/articles.html',
            controller: 'ArticlesCtrl'
          })
          .when('/gallery', {
            templateUrl: 'views/gallery.html',
            controller: 'GalleryCtrl'
          })
          .when('/subscribers', {
            templateUrl: 'views/subscribers.html',
            controller: 'SubscribersCtrl'
          })
          .otherwise({
            redirectTo: '/'
          });
      });

    The 'use strict' command that you see at the start of most of our files is a new feature of ECMAScript 5, which makes the file or function operate in a strict context. You can read more about it at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode.

    Building the articles view

    Let’s create the articles view by first creating our data model within the app/scripts/controllers/articles.js file.

    Let’s delete the default awesomeThings array and replace it with the following lines of code:

    $scope.posts = [
    {
    title:"Almonds are good for Health",
    content:"Almonds contain high amounts of HDL which helps reduce cholestrol.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus rhoncus quam leo, id tristique sapien viverra eu. Maecenas ipsum lectus, suscipit auctor tristique in, venenatis ut nisl. Quisque eget bibendum libero. Nam nec mi augue."
    },
    {
    title:"Sugar is bad for health",
    content:"Sugar besides being bad for diabetes, it also causes overweight and obesity problems. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus rhoncus quam leo, id tristique sapien viverra eu. Maecenas ipsum lectus, suscipit auctor tristique in."
    },
    {
    title:"Cut down your carbs!!!",
    content:"Sugar besides being bad for diabetes, it also causes overweight and obesity problems.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus rhoncus quam leo, id tristique sapien viverra eu. Maecenas ipsum lectus, suscipit auctor tristique in, venenatis ut nisl. Quisque eget bibendum libero. Nam nec mi augue."
          }
    
           ];

    By now, I’m sure you are well versed of the structure of the preceding data model.

    With regard to generating the dummy lorem lipsum text, www.lipsum.com is one of the best places to generate your summary text. Nowadays, many IDEs too have snippets, plugins, or macros to generate the lorem lipsum code.

    Note

    Lorem lipsum was invented sometime in the 1500s when an unknown printer took a galley of type and scrambled it to make a type specimen book. Since then, it has been used extensively in the type setting and printing industry and has also made it into the electronic age.

    Accordions using Angular Bootstrap



    Now that our model is ready, let’s get to the partial. We will display the preceding model data within an accordion.

    As per our routes setting, ArticlesCtrl is mapped to the views/articles.html file; hence, we’ll write our markup in this file.

    Open the app/views/articles.html file and write the following code:

    <h1>Articles</h1>
    <accordion>
       <accordion-group heading=" {{post.title}}" ng-repeat="post in posts">
             {{post.content}}
       </accordion-group>
    </accordion>

    The first line sets the page title within the Heading tag.

    Next, we call our directive to display the accordion. The <accordion> tag can contain multiple <accordion-group> sections, each with a heading attribute and a body area.

    Using ng-repeat, we simply loop through the rows of data in our model and place them within the heading and content area.

    Save the file and navigate the browser to see your articles page in action. It should look something like the following screenshot:

    Building the image gallery

    The next step is to build our image gallery, so let’s create the controller, partial, and routes for it using the Yeoman command as follows:

    yo angular:route gallery

    We will start with the creation of our model in the app/scripts/controllers/gallery.js file.

    This time, rather than creating static object models in the controller, we’ll define a set of arrays and create our model dynamically. This would be a much more efficient way of building the models, especially if you have a large amount of data.

    Let’s start by defining the various variables and arrays that we will need within the GalleryCtrl controller function as follows:

    var pictures =$scope.pictures=[];
    
    var baseURL="http://lorempixel.com/300/180/";
    
    var titles=["Healthy Food","Healthy @ Work","City Life ",
                 "Staying Fit","Looking Good","Nightlife !!"] ;
    
    var keywords=["food", "business","city","sports","fashion", 
                   "nightlife"];
    
    var dummyText="Lorem ipsum dolor sit amet, consectetur adipiscing 
                    elit. Sed sed erat turpis. Integer eget 
                    consectetur quam. Sed at quam ut dolor varius 
                    condimentum et sit amet odio. "

    First, we declare an empty model named pictures.

    The next variable we define is baseURL, which holds the base URL for the images that we will show in the image gallery. As you can notice, in this case, we are using images of width 300 and height 180.

    Next, titles is the array containing the titles for all the images.

    The keywords array holds the list of all the keywords that we will concatenate at the end of baseURL to get relevant images for the gallery.

    Finally, the dummyText variable holds some lorem ipsum text that we will add as a description to each of the gallery images.

    Now that we have all the variables and arrays defined, the next step is to create the function that will push them into the pictures model.

    The function is defined as follows:

    $scope.addPics=function(i){
       pictures.push({
             url:baseURL+keywords[i],
             title:titles[i],
             summary:dummyText
        })
    }

    The addPics function takes in an input parameter i, which does an array push by iterating through the arrays and updating the values for the url, title, and summary properties.

    The final step here is to call the addPics function in a loop, incrementing the value of i. This is done as follows:

    for (var i=0;i<5;i++){
        $scope.addPics(i);
    }

    As, for this example, we need about six images, we run a for loop iterating from 0 to 5.

    This completes our work on the controller. Now, let’s look at the markup for the gallery partial.

    Gallery view using Bootstrap Thumbnail

    Angular Bootstrap doesn’t have any special directive to create or display the thumbnails for the gallery view; hence, we will be using the regular Bootstrap classes to create our view.

    Let’s open the views/gallery.html file and write the following code:

    <h1>Gallery</h1>
    <div class="thumbnails">
       <div class="col-md-4" ng-repeat="pic in pictures">
          <img ng-src="{{pic.url}}">
          <h3>{{pic.title}}</h3>
          <p> {{pic.summary}}</p>
       </div>
    </div>

    Save the file and switch to your browser to see your gallery page in action. Ensure your images take the full width of the column by adding the following CSS lines:

    .thumbnails img{
    width:100%}

    Note

    In case the page doesn’t show up, open up the console either in Firebug or Chrome developer tools to see if any JavaScript errors are throwing up. Try and fix these errors to get your page to work.

    Adding the star rating

    Let’s make our gallery page a little more interesting by adding in the star rating feature. Thanks to Angular Bootstrap, adding this feature is as simple as adding one line of code in the partial. So, let’s open up the app/views/gallery.html file and add the following highlighted line:

    <h1>Gallery</h1>
    <div class="thumbnails">
       <div class="col-md-4" ng-repeat="pic in pictures">         
       <img src="{{pic.url}}">
       <rating ng-model="rate" max="max" readonly="isReadonly" ></rating>
              <h3>{{pic.title}}</h3>
              <p> {{pic.summary}}</p>
       </div>
    </div>

    In the app/scripts/controllers/gallery.js controller, we simply need to define the following values

    $scope.rate = 0;
    $scope.max = 10;
    $scope.isReadonly = false;

    Save the file and view the gallery page in the browser. It should now look like the following screenshot:

    Building data grids using NG-Grid



    Tables or data grids are something that we need to add in our applications quite often. At the beginning, creating tables is fairly simple; you simply create a <table> tag and populate the rows and columns. However, as you proceed, things get complicated; you will be asked to allow sorting on columns, or you will have to paginate through multiple rows and, at times, you will even be asked to allow inline editing like Excel.

    Thanks to NG-Grid, creating such feature-rich data grids in angularjs has become very easy.

    Adding the NG-Grid component

    NG-Grid is not a part of Angular Bootstrap and needs to be added separately. Let’s use Bower to download the components for NG-Grid. In your terminal, navigate to your project folder, and type in the following command lines:

    cd hl
    bower install ng-grid

    You should now be able to see the ng-grid folder and the files within the bower_components folder.

    The next thing is to include the ng-grid JS and CSS files in our index.html file. Add the following highlighted line in your app/index.html file to include the ng-grid CSS file:

    <link rel="stylesheet" href="styles/bootstrap.css">
    <link rel="stylesheet" href="bower_components/ng-grid/ng-grid.css">
    <link rel="stylesheet" href="styles/main.css">

    Note

    Make sure that the main.css file is the last file being called so that whatever style customization that you write in the main.css overrides the others.

    Add the ng-grid JS file as highlighted in the following code snippet:

    <script src="bower_components/jquery/dist/jquery.js"></script>
    <script src="bower_components/angular/angular.js"></script>
    <script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
    <script src="bower_components/ng-grid/ng-grid-2.0.11.min.js"></script>
    

    Next, we need to add the ngGrid dependency to hlApp. We’ll do this by adding it in our app/scripts/app.js file as follows:

    angular.module('hlApp', ['ui.bootstrap','ngGrid'])

    Now that we have NG-Grid added to our projects, let’s create the routes, controllers, and partials for the subscribers page.

    Open up the terminal and run the following command:

    yo angular:route subscribers
    

    Once we are done with this, we are all set to start working on our subscribers view.

    In most practical cases, we would call a web service that would return the list of subscribers. We can simulate a web service response by creating a static JSON file and putting in some dummy values.

    Let’s create a file in the app folder named subscribers.json and add in the following dummy JSON data:

    [
    {"no": "1","name":"Betty", "loyalty": 3,"joinDate":"3/5/10"},
    {"no": "2","name":"John", "loyalty": 5,"joinDate":"3/5/05"},
    {"no": "3","name":"Peter", "loyalty": 6,"joinDate":"3/5/10"},
    {"no": "4","name":"Jaden", "loyalty": 7,"joinDate":"10/12/12"},
    {"no": "5","name":"Shannon", "loyalty": 9,"joinDate":"22/01/08"}
    ]

    Let’s see how to load this data into our controller.

    Add the following highlighted code within the SubscribersCtrl controller located in the app/scripts/subscribers.js file:

    .controller('SubscribersCtrl', function ($scope,$http) {
    $http.get('http://localhost:9000/subscribers.json').success(function(data){
       $scope.subscribers =data
    })
    })

    From the preceding code, you’ll notice that we are injecting the $http service into our controller, and we use the $http.get method to make an HTTP request to the subscribers.json file.

    The $http service will return a promise that contains two methods, namely success and error.

    Within the success method, we populate our subscribers model with the returned data.

    Now that the model is ready, we need to initialize NG-Grid, so let’s initialize ng-grid as follows:

    $scope.gridOptions = { 
        data: 'subscribers'
    };

    Our work on the controller is done. Let’s open the app/views/subscribers.html partial and add the markup for the grid using the following lines of code.

    <h1>Subscribers</h1>
    <div class="gridStyles" ng-grid="gridOptions">
    </div>

    We’ll also need to define the width and height of the grid. We’ll do this by setting the width and height properties in the CSS.

    Open up the app/styles/main.css file and add the height and width properties to the .gridStyles class.

    .gridStyles{
        width:940px;
        height:300px;
    }

    Note

    It is important to define at least the height property so that NG-Grid knows the area within which it should render the grid. If you miss out the height property, NG-Grid will by default take the height of the parent container, which sometimes will display just one row of data when you scroll.

    Save the file and refresh the browser to see NG-Grid in action. Click on the column headings to see them sorted.

    Note

    Sometimes, you’ll need to do a hard refresh to let NG-Grid know about any CSS changes that you would have made.

    Right now, NG-Grid uses the model property names as the column headings. Many a times, this would not be ideal as one would want to define their own custom headers. This is possible by defining the Column Definitions property in gridOptions.

    To add the Column Definitions property, open the app/scripts/controllers/subscribers.js file and add the following highlighted code:

    $scope.gridOptions = { 
        data: 'subscribers',
            columnDefs: [
            {field:'no', displayName:'No.'}, 
            {field:'name', displayName:'Name'}, 
            {field:'loyalty', displayName:'Loyalty Score'},
            {field:'joinDate', displayName:'Date of Joining'}]
    };

    Save the file and navigate to the browser to see the new column heading take effect.

    Now, the obvious question that arises is: how do we customize the alternating row colors? This can be done by simply overriding the default odd and even row classes by adding the following classes to the app/styles/main.css file:

    .ngRow.even {
        background: AliceBlue;
    }
    .ngRow.odd {
        background: YellowGreen;
    }

    This should now give you a table grid with alternating rows of light-blue and green backgrounds.

    Grouping data in NG-Grid

    The NG-Grid is quite feature-rich, and besides the regular column sorting and alternating rows, it also allows for features such as the grouping of data by a column and Excel-style inline editing.

    Let’s see how data grouping in NG-Grid works. For this to look better and work more efficiently let’s create a new attribute called Subscription Type in our models and use it for grouping.

    Let’s add a new property to our subscribers list in our subscribers.json file as highlighted in the following lines of code:

    [
    {"no":"1", "name":"Betty", "loyalty": 3,"joinDate":"3/5/10", "userType":"Free"},
    {"no":"2", "name":"John", "loyalty": 5,"joinDate":"3/5/05", "userType":"Premium"},
    {"no":"3", "name":"Peter", "loyalty": 6,"joinDate":"3/5/10", "userType":"Free"},
    {"no":"4", "name":"Jaden", "loyalty": 7,"joinDate":"10/12/12", "userType":"Premium"},
    {"no":"5", "name":"Shannon", "loyalty": 9,"joinDate":"22/01/08", "userType":"Premium"}
    ]

    We’ll also add it to the column definitions in the gridOptions settings.

    $scope.gridOptions = { 
        data: 'subscribers',
            columnDefs: [
            {field:'no', displayName:'No.'}, 
            {field:'name', displayName:'Name'}, 
            {field:'userType', displayName:'Subscription Type'}, 
            {field:'loyalty', displayName:'Loyalty Score'},
            {field:'joinDate', displayName:'Date of Joining'}]
    
    };

    Save the file and verify that the Subscription Type column is now visible on the Subscriptions view.

    Now, we’d like the user to drag a column into the group area and group the rows based on the selected column, something like the data-filters feature in the Excel Pivot tables.

    Enabling this in NG-Grid is very simple; you simply need to add the following parameter to gridOptions in app/scripts/controllers/subscribers.js as highlighted in the following lines of code:

    $scope.gridOptions = { 
        data: 'subscribers',
        showGroupPanel: true,
        columnDefs: [
            {field:'no', displayName:'No.'}, 
            {field:'name', displayName:'Name'}, 
            {field:'userType', displayName:'Subscription Type'}, 
            {field:'loyalty', displayName:'Loyalty Score'},
            {field:'joinDate', displayName:'Date of Joining'}]
    
    };

    Save the file and refresh the Subscriptions view in your browser. You should now see a new area above the column headings. Drag the Subscription Type column heading and drop it in the area above it.

    Note that the data in your grid has been grouped on the basis of the subscription type, and it also tells you the total number of users within each group. This is demonstrated in the following screenshot:

    Excel-style editing in NG-Grid

    I’m sure many of you come across this requirement where you need to allow for inline editing within a data grid. Trying to do this using the regular jQuery and Ajax can be quite an effort. Now, with NG-Grid, it’s just about enabling these settings within gridOptions.

    Open the app/scripts/controllers/subscribers.js file and add the following highlighted parameter to gridOptions:

    $scope.gridOptions = { 
        data: 'subscribers',
        showGroupPanel: true,
        jqueryUIDraggable: true,
        enableCellSelection: true,
        enableRowSelection: false,
        enableCellEdit: true,
       columnDefs: [
            {field:'no', displayName:'No.'}, 
            {field:'name', displayName:'Name'}, 
            {field:'userType', displayName:'Subscription Type'}, 
            {field:'loyalty', displayName:'Loyalty Score'},
            {field:'joinDate', displayName:'Date of Joining'}]
    
    };

    Save the file, and in the Subscriptions view in the browser, try double-clicking on any one of the cells, change the text, and press Enter. As simple as that! The following screenshot is the output obtained:

    Creating a modal window to add subscribers

    Now that we have a feature-rich data grid displaying our subscribers, let’s create a modal window with a form to add users to our subscribers model.

    Adding a modal window using Angular UI is a little more complicated than the rest of the components we have seen until now.

    To start with, we will need a button that will launch the modal window when it is clicked on.

    We will create this button in the app/views/subscribers.html file with the following highlighted lines of code:

    <h1>Subscribers</h1>
    <button class="btn btn-success" ng-click="showModal()"> Add New User</button>   
    <div class="gridStyles" ng-grid="gridOptions">
    </div>

    The .btn class sets the button’s basic styles such as rounded corners, font size, padding, and so on. The .btn-success class gives it the green color. In the ng-click directive, we are calling a function named showModal.

    We will now create the partial for the modal view. Create a new file called add-user.html within the app/views folder, and let’s put in the markup for the Add New User form as follows:

    <div class="modal-header">
       <button type="button" class="close" ng-click="cancel()" data-dismiss="modal" aria-hidden="true">&times;</button>
       <h1>Add a Subscriber</h1>
    </div>

    We define the heading for the modal window by applying the .modal-header class.

    We also place our close button within the header.

    Next, we will mark up the content for the modal body.

    <div class="modal-body"> 
    <label>Name</label><input type="text" ng-model="newUser.name"/>
    <label>Subscription Type</label><input type="text" ng-model="newUser.userType"/>
    <label>Loyalty Score</label><input type="number" ng-model="newUser.loyalty"/>
    <label>Date of Joining</label><input type="date" ng-model="newUser.joinDate"/>
    <br/>
    <button class="btn btn-success" ng-click="saveNewUser()"> Save User</button>
    
    </div>

    The code is straightforward; we wrap our form elements within a <div> with the .modal-body class.

    We have four form elements, which are tied to the respective properties of the newUser object.

    The Add New User button, when clicked on, will call the AddNewUser function.

    Note

    Note the type attributes for each of the input elements. These type attributes are automatically used by modern browsers for validations. angularjs too appends its own CSS class to enable real-time validation notifications.

    Next, we will add the code to our app/scripts/controllers/subscribers.js file.

    The modal window makes use of the $modal service, so we will need to add it to SubscribersCtrl as highlighted in the following lines of code:

    angular.module('hlApp')
      .controller('SubscribersCtrl', function ($scope,$http, $modal) {

    Next, we will write the code to call the modal window.

    As the Add New User button function will call the showModal function when clicked on, we will define that function at the end, just above the closing braces of our SubscribersCtrl controller as follows:

    $scope.showModal=function () {
    $scope.newUser={};
        var modalInstance = $modal.open({
          templateUrl: 'views/add-user.html'})}

    The $modal service has a method named open(), with a couple of options, templateUrl being one of them.

    We are also creating an empty model object named newUser. We will be using this to store the form data from the modal window.

    Save the file and test it in the browser. Clicking on the Add New User Button should slide the modal window into view. However, this is quite static, and neither the close button nor the Save User buttons will work because we haven’t yet coded in the saveNewUser() or cancel() functions.

    An important thing to note is that the $modal service will create its own scope within the parent scope.

    Another option that the $modal.open method supports is the controller that allows you to assign another controller, that binds to the view within the modal. Let us now add the controller option to modalInstance.

    $scope.showModal= function () {
        var modalInstance = $modal.open({
          templateUrl: 'views/add-user.html',
          controller:'AddNewUserCtrl'
    
        })}

    Next, we’ll create AddNewUserCtrl within the same app/scripts/controllers/subscribers.js file.

    We add this controller right at the end of the file after the SubscribersCtrl function ends as follows:

    .controller('AddNewUserCtrl', function ($scope, $modalInstance) {
    });

    Tip

    Don’t forget to remove the semicolon at the end of the SubscribersCtrl function.

    Now, within AddNewUserCtrl, we’ll define the functions for the Cancel button as follows:

     .controller('AddNewUserCtrl', function ($scope, $modalInstance) {
      $scope.cancel =function(){
        $modalInstance.dismiss('cancel');
      };
    });

    Save the files and check to see if the Add New User and the Cancel buttons are working. Add the following CSS class to get your form to look aligned:

    .modal-body input{
    display:block;
    }

    You should be seeing something like the following screenshot:

    Now, let’s add the rest of the code to save the user.In the AddNewUserCtrl controller, add the following highlighted code:

    .controller('AddNewUserCtrl', function ($scope, $modalInstance,newUser) {
    $scope.newUser=newUser;
    $scope.saveNewUser=function(){
      $modalInstance.close(newUser);
    };
    
      $scope.cancel =function(){
        $modalInstance.dismiss('cancel');
      }
    
    });

    We’ll now add the last option to our $modal.open method, which is named resolve. The code is highlighted as shown in the following lines of code:

    var modalInstance = $modal.open({
    templateUrl: 'views/add-user.html',
    controller: 'AddUserCtrl',
    resolve: {
       newUser: function () {
       return $scope.newUser;
            }
          }
        });

    Like most services, $modal also makes use of promises to return the objects and variables that have been asked for.

    Here, in the resolve part, we are returning the newUser model object.

    Now that we have the newUser model returned to us as a response to the promise, we need push the data from it into our subscribers model. This is done by the following piece of code:

    modalInstance.result.then(function (selectedItem) {
    $scope.subscribers.push({
    no:$scope.subscribers.length+1,
    name:$scope.newUser.name,
    userType:$scope.newUser.userType,
    loyalty:$scope.newUser.loyalty,
    joinDate:$scope.newUser.joinDate
    
      });
    });

    Notice that for the no column, I’m simply taking the length of our current model and incrementing it by 1.

    Also note that the preceding code is written within the showModal function.

    The complete code for showModal should be as follows:

    $scope.showModal=function () {
       $scope.newUser={};
        var modalInstance = $modal.open({
          templateUrl: 'views/add-user.html',
          controller:'AddNewUserCtrl',
          resolve: {
             newUser: function () {
            return $scope.newUser;
            }
          }
    
    
        })
    
        modalInstance.result.then(function (selectedItem) {
        $scope.subscribers.push({
        no:$scope.subscribers.length+1,
        name:$scope.newUser.name,
        userType:$scope.newUser.userType,
        loyalty:$scope.newUser.loyalty,
        joinDate:$scope.newUser.joinDate
    
          });
        });
    
      }

    Real-time form validations

    Based on the type attribute of your input fields, angularjs is adding the ng-valid and ng-invalid classes in real time. We can take advantage of this to give constructive feedback to the user.

    What we will do is, if the entered text is valid, the text box will have a green border, and if the data in the text box is invalid, it will have a red border.

    To achieve this, we will add the following CSS properties for these classes in the app/styles/main.css file:

    .ng-valid{
        border: thin solid #090;
    }
    .ng-invalid{
        border: thin solid #990000;
    }

    With this, we complete our tutorial of creating the clickable prototype.

    In conclusion the following are a couple of reasons why building clickable prototypes in angularjs is a good idea:

    • It gives a clear picture to all the stakeholders on how the application is going to look and work.
    • One can get valuable usability feedback and easily identify any usability issues by simply playing around with the prototype.
    • The Presentation Layer code is production-ready, and during the actual time of development, we only need to swap the static data models with dynamic ones from web services. This will significantly cut down the development time.
    • The time taken to build the click flows in angularjs is much lesser than it would take if done using the regular HTML, CSS, and jQuery. Using regular HTML and CSS would also generate quite a bit of throw-away code, which isn’t very efficient.

    In this Tutorial, we saw how to keep the data separate from the presentation layer. I’m sure you also appreciated how we had to write very few lines of code to build the entire application.

    We used Yeoman to scaffold our app and create the new pages that we wanted. We used the custom directives from Angular Bootstrap for the various components that we used across the application.

    We also saw how routes work and how views and controllers are bound to a path using routeProvider.

    We took advantage of Bootstrap’s grid system and the predefined classes to build the entire website without having to write any large amounts of custom CSS code.

    Deven Rathore

    Deven is an Entrepreneur, and Full-stack developer, Constantly learning and experiencing new things. He currently runs CodeSource.io and Dunebook.com.

    Published by
    Deven Rathore

    Recent Posts

    Are There any Similarities Between Web Design and Art?

    You may be surprised at how many of the same skills are involved!  Let’s get…

    1 day ago

    Tips on Increasing your organic traffic on WordPress

    Introduction  As more and more people are using online services nowadays, most of the business…

    2 days ago

    Five Reasons You Should Start a Social Media Campaign

    Small businesses need all the advertisements they can get. Traditional avenues for advertising, such as…

    3 days ago

    Top 10 SEO Writing Tips for Beginners 2021

    Search Engine Optimization. It’s complicated, to say the least. Search engines, like Google, are constantly…

    2 weeks ago

    Should you become a freelancer in 2021? Pros and Cons

    Freelancing and working from home was long considered idyllic by many, but the global pandemic…

    2 weeks ago

    The Leading Renewable Energy Trends in 2021

    The past year saw slowdowns in the ongoing shift toward renewable energy in many countries…

    2 weeks ago