Nesting AngularJS Custom Directives

If you haven’t gone through my previous articles on AngularJS custom directives please have a look at it from the following links.

This article would be an extension of my previous articles. Here we’ll try to understand how do we nest one AngularJS custom directive inside another. Well there are ample situations where you’ll need to nest one custom directive inside another.

Let’s consider an example of a social media website where a user post some content and his friends likes or comments on that post. Posting a content is one part (i.e. it becomes our 1st directive) and likes or commenting on that post is another part (i.e. it becomes our nested directive). To demonstrate this look at the following snapshot:

AngularJS Custom Directives

For demonstrating this article we’ll try to implement the above scenario. I’m using VS2013 Mvc4 application, also I have added the necessary AngularJS script and boostrap css files in the application. Let’s get into the code now.

_Layout.cshtml

  1. <!DOCTYPE html>  
  2. <html ng-app="myApp">  
  3. <head>  
  4.     <meta charset="utf-8" />  
  5.     <meta name="viewport" content="width=device-width" />  
  6.     <title>@ViewBag.Title</title>  
  7.     <link href="~/Content/bootstrap.min.css" rel="stylesheet" />  
  8.     @Scripts.Render("~/bundles/jquery")  
  9.     <script src="~/Scripts/angular.min.js"></script>  
  10.     @RenderSection("scripts", required: false)  
  11. </head>  
  12. <body class="container">  
  13.     @RenderBody()  
  14. </body>  
  15.   
  16. </html>  
userPost.html (our Parent AngularJS Directive)
  1. <div>  
  2.     <div ng-repeat="user in userDetails">  
  3.         <div ng-repeat="post in user.Posts">  
  4.             <div class="panel panel-default panel-primary">  
  5.                 <div class="panel-heading">  
  6.                     <h5><strong>{{user.Name}}</strong></h5>  
  7.                 </div>  
  8.                 <div class="panel-body">  
  9.                     <img ng-src="{{post.Content}}" alt="Image" class="img-responsive" />  
  10.                 </div>  
  11.                 <div class="panel-footer">  
  12.                     <!--Nesting another angularJs Custom Directive-->  
  13.                     <user-likes likes-count="{{post.Likes.length}}"></user-likes>  
  14.                 </div>  
  15.             </div>  
  16.         </div>  
  17.     </div>  
  18. </div>  
userLikes.html (our Nested/Child AngularJS Directive)
  1. <div>  
  2.     <button class="btn btn-primary" type="button">  
  3.         Likes <span class="glyphicon glyphicon-thumbs-up"></span>  
  4.     </button>  
  5.     <!--Binding the likesCount model-->  
  6.     <span class="badge">{{likesCount}}</span>  
  7. </div>  
Index.cshtml
  1. @{  
  2.     ViewBag.Title = "Index";  
  3.     Layout = "~/Views/Shared/_Layout.cshtml";  
  4. }  
  5. @section scripts  
  6. {  
  7.     <script src="~/Scripts/app/Home.js"></script>  
  8. }  
  9. <style>  
  10.     .img {  
  11.     }  
  12. </style>  
  13. <div ng-controller="homeController" class="table-responsive">  
  14.     <user-posts user-details="users">  
  15.     </user-posts>  
  16. </div>  
Home.js
  1. var myApp = angular.module("myApp", []);  
  2.   
  3. //Creating Service for retrieving Data  
  4. myApp.service("ConnectAppDataService", function () {  
  5.   
  6.     this.GetConnectAppUserDetails = function () {  
  7.         var ConnectAppUserDetails = [  
  8.             {  
  9.                 UserId: "1",  
  10.                 Name: "Vishal Gilbile",  
  11.                 Posts: [  
  12.                     {  
  13.                         PostId: "1",  
  14.                         Content: "../../Content/images/images11.jpg",  
  15.                         Likes: [  
  16.                             {  
  17.                                 LikeId: "1",  
  18.                                 UserId: "2",  
  19.                             },  
  20.                             {  
  21.                                 LikeId: "2",  
  22.                                 UserId: "4"  
  23.                             }  
  24.                         ]  
  25.                     },  
  26.                     {  
  27.                         Post: "2",  
  28.                         Content: "../../Content/images/images2.jpg",  
  29.                         Likes: [  
  30.                             {  
  31.                                 LikeId: "3",  
  32.                                 UserId: "2",  
  33.                             },  
  34.                             {  
  35.                                 LikeId: "4",  
  36.                                 UserId: "4"  
  37.                             },  
  38.                             {  
  39.                                 LikeId: "5",  
  40.                                 UserId: "3"  
  41.                             }  
  42.                         ]  
  43.                     }  
  44.                 ]  
  45.             },  
  46.             {  
  47.                 UserId: "2",  
  48.                 Name: "Lincy Pullan",  
  49.                 Posts: [  
  50.                     {  
  51.                         PostId: "3",  
  52.                         Content: "../../Content/images/images4.jpg",  
  53.                         Likes: [  
  54.                             {  
  55.                                 LikeId: "6",  
  56.                                 UserId: "3"  
  57.                             },  
  58.                             {  
  59.                                 LikeId: "7",  
  60.                                 UserId: "1"  
  61.                             }  
  62.                         ]  
  63.                     },  
  64.                     {  
  65.                         PostId: "4",  
  66.                         Content: "../../Content/images/images5.jpg",  
  67.                         Likes: [  
  68.                             {  
  69.                                 LikeId: "8",  
  70.                                 UserId: "1"  
  71.                             }  
  72.                         ]  
  73.                     },  
  74.                     {  
  75.                         PostId: "11",  
  76.                         Content: "../../Content/images/images6.jpg",  
  77.                         Likes: [  
  78.                             {  
  79.                                 LikeId: "9",  
  80.                                 UserId: "4"  
  81.                             }  
  82.                         ]  
  83.                     }  
  84.                 ]  
  85.             },  
  86.             {  
  87.                 UserId: "3",  
  88.                 Name: "Rahul Bandekar",  
  89.                 Posts: [  
  90.                     {  
  91.                         PostId: "5",  
  92.                         Content: "../../Content/images/images12.jpg",  
  93.                         Likes: [  
  94.                             {  
  95.                                 LikeId: "10",  
  96.                                 UserId: "1"  
  97.                             }  
  98.                         ]  
  99.                     },  
  100.                     {  
  101.                         PostId: "6",  
  102.                         Content: "../../Content/images/images8.jpg",  
  103.                         Likes: []  
  104.                     },  
  105.                     {  
  106.                         PostId: "7",  
  107.                         Content: "../../Content/images/images7.jpg",  
  108.                         Likes: [  
  109.                             {  
  110.                                 LikeId: "10",  
  111.                                 UserId: "1"  
  112.                             }  
  113.                         ]  
  114.                     }  
  115.                 ]  
  116.             },  
  117.             {  
  118.                 UserId: "4",  
  119.                 Name: "Muthu Konar",  
  120.                 Posts: [  
  121.                     {  
  122.                         PostId: "8",  
  123.                         Content: "../../Content/images/images3.jpg",  
  124.                         Likes: [  
  125.                             {  
  126.                                 LikeId: "11",  
  127.                                 UserId: "1"  
  128.                             },  
  129.                             {  
  130.                                 LikeId: "12",  
  131.                                 UserId: "4"  
  132.                             }  
  133.                         ]  
  134.                     },  
  135.                     {  
  136.                         PostId: "9",  
  137.                         Content: "../../Content/images/images10.gif",  
  138.                         Likes: [  
  139.                             {  
  140.                                 LikeId: "13",  
  141.                                 UserId: "2"  
  142.                             },  
  143.                             {  
  144.                                 LikeId: "14",  
  145.                                 UserId: "3"  
  146.                             }  
  147.                         ]  
  148.                     },  
  149.                     {  
  150.                         PostId: "10",  
  151.                         Content: "../../Content/images/images1.jpg",  
  152.                         Likes: []  
  153.                     }  
  154.                 ]  
  155.             }  
  156.         ];  
  157.         return ConnectAppUserDetails;  
  158.     };  
  159.   
  160. });  
  161.   
  162. //Home Controller  
  163. myApp.controller("homeController", ["$scope""ConnectAppDataService", function ($scope, ConnectAppDataService) {  
  164.     $scope.users = ConnectAppDataService.GetConnectAppUserDetails();  
  165.     //console.log("homeController", $scope);  
  166. }]);  
  167.   
  168.   
  169. //UserPost Directive  
  170. myApp.directive("userPosts", function () {  
  171.     return {  
  172.         restrict: "E",  
  173.         templateUrl: "../../Directives/userPosts.html",  
  174.         scope: {  
  175.             userDetails: "="  
  176.         }  
  177.     }  
  178. });  
  179.   
  180. //UserLikes Directive  
  181. myApp.directive("userLikes", function () {  
  182.     return {  
  183.         restrict: "E",  
  184.         templateUrl: "../../Directives/userLikes.html",  
  185.         scope: {  
  186.             likesCount: '@'  
  187.         }  
  188.     }  
  189. });  
Now let’s run the application and you’ll see the following output.

output