How To Create A Grid Dynamically Using Angular

Introduction
 
AngularJS provides various features. One of them is 2-way data binding. In this article, I will explain how to create Grid dynamically using Angular.

AngularJS
 
Download the requred JavaScript and css files from the below links
Get Started
  • Open Visual Studio and create a new MVC web application.
  • Copy the downloaded AngularJS file in "Scripts" folder of the solution.
  • Create a JavaScript file and name it as Module.js.
  • Then, write the following code in it.
    1. var app = angular.module("myApp",[]);    
  • Create another JavaScript file and name it as Controller.js.
  • Start writing code as given below.
    1. app.controller("gridController"function($scope, $rootScope) {  
    2.             var data = [];  
    3.             var columns = [];  
    4.             columns.push({  
    5.                 "key""Status",  
    6.                 "width""5%",  
    7.                 "dataType""status",  
    8.                 "showTags""false",  
    9.                 "showColumns""true"  
    10.             });  
    11.             columns.push({  
    12.                 "key""ID",  
    13.                 "width""1%",  
    14.                 "dataType""string",  
    15.                 "showTags""false",  
    16.                 "showColumns""true"  
    17.             });  
    18.             columns.push({  
    19.                 "key""Critical",  
    20.                 "width""1%",  
    21.                 "dataType""bool",  
    22.                 "showTags""true",  
    23.                 "showColumns""false"  
    24.             });  
    25.             columns.push({  
    26.                 "key""CSM",  
    27.                 "width""1%",  
    28.                 "dataType""bool",  
    29.                 "showTags""true",  
    30.                 "showColumns""false"  
    31.             });  
    32.             columns.push({  
    33.                 "key""E0/EC0",  
    34.                 "width""1%",  
    35.                 "dataType""bool",  
    36.                 "showTags""true",  
    37.                 "showColumns""true"  
    38.             });  
    39.             columns.push({  
    40.                 "key""MT2",  
    41.                 "width""5%",  
    42.                 "dataType""bool",  
    43.                 "showTags""true",  
    44.                 "showColumns""false"  
    45.             });  
    46.             columns.push({  
    47.                 "key""MT3",  
    48.                 "width""5%",  
    49.                 "dataType""bool",  
    50.                 "showTags""true",  
    51.                 "showColumns""false"  
    52.             });  
    53.             columns.push({  
    54.                 "key""Component",  
    55.                 "width""9%",  
    56.                 "dataType""string",  
    57.                 "showTags""false",  
    58.                 "showColumns""true"  
    59.             });  
    60.             columns.push({  
    61.                 "key""Class Code",  
    62.                 "width""3%",  
    63.                 "dataType""string",  
    64.                 "showTags""false",  
    65.                 "showColumns""true"  
    66.             });  
    67.             columns.push({  
    68.                 "key""Caption",  
    69.                 "width""13%",  
    70.                 "dataType""string",  
    71.                 "showTags""false",  
    72.                 "showColumns""true"  
    73.             });  
    74.             columns.push({  
    75.                 "key""Dept",  
    76.                 "width""1%",  
    77.                 "dataType""string",  
    78.                 "showTags""false",  
    79.                 "showColumns""true"  
    80.             });  
    81.             columns.push({  
    82.                 "key""Rank",  
    83.                 "width""1%",  
    84.                 "dataType""string",  
    85.                 "showTags""false",  
    86.                 "showColumns""true"  
    87.             });  
    88.             columns.push({  
    89.                 "key""Interval",  
    90.                 "width""3%",  
    91.                 "dataType""string",  
    92.                 "showTags""false",  
    93.                 "showColumns""true"  
    94.             });  
    95.             columns.push({  
    96.                 "key""Start Date",  
    97.                 "width""4%",  
    98.                 "dataType""date",  
    99.                 "showTags""false",  
    100.                 "showColumns""false"  
    101.             });  
    102.             columns.push({  
    103.                 "key""End Date",  
    104.                 "width""4%",  
    105.                 "dataType""date",  
    106.                 "showTags""false",  
    107.                 "showColumns""false"  
    108.             });  
    109.             columns.push({  
    110.                 "key""Date/ Hours",  
    111.                 "width""3%",  
    112.                 "dataType""date",  
    113.                 "showTags""false",  
    114.                 "showColumns""true"  
    115.             });  
    116.             columns.push({  
    117.                 "key""Action",  
    118.                 "width""4%",  
    119.                 "dataType""commands",  
    120.                 "showTags""false",  
    121.                 "showColumns""true"  
    122.             });  
    123.             $rootScope.columns = eval(columns);  
    1. data.push({  
    2.     "Status": [{  
    3.         "val""Overdue",  
    4.         "color""label label-danger"  
    5.     }],  
    6.     "Start Date""2017-05-11",  
    7.     "End Date""2017-05-11",  
    8.     "Critical""true",  
    9.     "CSM""true",  
    10.     "E0/EC0""false",  
    11.     "MT2""CRI",  
    12.     "Component""Me Cyl. Head [6]",  
    13.     "Class Code""MDECYA",  
    14.     "Caption""OVH, TST, CLN OF Me Cyl. Head [6]",  
    15.     "Dept""ENG",  
    16.     "Rank""2E",  
    17.     "ID""00006",  
    18.     "Interval""6000 R/Hs",  
    19.     "Date/ Hours""6129 R/Hs",  
    20.     "Action"""  
    21. });  
    22. data.push({  
    23.     "Status": [{  
    24.         "val""Overdue",  
    25.         "color""label label-danger"  
    26.     }, {  
    27.         "val""P",  
    28.         "color""label label-info",  
    29.         "title""Planned"  
    30.     }],  
    31.     "Start Date""2017-05-09",  
    32.     "End Date""2017-05-11",  
    33.     "Critical""false",  
    34.     "CSM""false",  
    35.     "E0/EC0""false",  
    36.     "Component""Me Injector Valves W/Pipes [3]",  
    37.     "Class Code""MDECYA",  
    38.     "Caption""TST, INSP OF Me Injector Valves W/Pipes [3]",  
    39.     "Dept""ENG",  
    40.     "Rank""CE",  
    41.     "ID""00011",  
    42.     "Interval""500 R/Hs",  
    43.     "Date/ Hours""2812 R/Hs",  
    44.     "Action"""  
    45. });  
    46. data.push({  
    47.     "Status": [{  
    48.         "val""Due",  
    49.         "color""label label-success"  
    50.     }],  
    51.     "Start Date""2017-05-01",  
    52.     "End Date""2017-05-01",  
    53.     "Critical""true",  
    54.     "CSM""true",  
    55.     "E0/EC0""true",  
    56.     "Component""Me Fo Pre-Heater",  
    57.     "Class Code""",  
    58.     "Caption""TST, CLN, INSP OF Me Fo Pre-Heater",  
    59.     "Dept""ENG",  
    60.     "Rank""2E",  
    61.     "ID""00150",  
    62.     "Interval""30 M",  
    63.     "Date/ Hours""5/20/2017",  
    64.     "Action"""  
    65. });  
    66. data.push({  
    67.     "Status": [{  
    68.         "val""Overdue",  
    69.         "color""label label-danger"  
    70.     }],  
    71.     "Start Date""2017-05-04",  
    72.     "End Date""2017-05-04",  
    73.     "Critical""false",  
    74.     "CSM""false",  
    75.     "E0/EC0""true",  
    76.     "Component""Me Flowmeter",  
    77.     "Class Code""",  
    78.     "Caption""INSP, CLN OF Me Flowmeter",  
    79.     "Dept""ENG",  
    80.     "Rank""2E",  
    81.     "ID""00151",  
    82.     "Interval""30 M",  
    83.     "Date/ Hours""5/19/2017",  
    84.     "Action"""  
    85. });  
    86. data.push({  
    87.     "Status": [{  
    88.         "val""Due",  
    89.         "color""label label-success"  
    90.     }],  
    91.     "Start Date""2017-05-04",  
    92.     "End Date""2017-05-04",  
    93.     "Critical""true",  
    94.     "CSM""true",  
    95.     "E0/EC0""true",  
    96.     "Component""Ae Cyl. Head [1] [3]",  
    97.     "Class Code""MDECYA",  
    98.     "Caption""OVH, INSP OF Ae Cyl. Head [1] [3]",  
    99.     "Dept""ENG",  
    100.     "Rank""3E",  
    101.     "ID""00164",  
    102.     "Interval""1500 R/Hs",  
    103.     "Date/ Hours""3845 R/Hs",  
    104.     "Action"""  
    105. });  
    106. data.push({  
    107.     "Status": [{  
    108.         "val""Due",  
    109.         "color""label label-success"  
    110.     }],  
    111.     "Start Date""2017-05-01",  
    112.     "End Date""2017-05-02",  
    113.     "Critical""false",  
    114.     "CSM""false",  
    115.     "E0/EC0""true",  
    116.     "Component""D/E Frequency Low [1]",  
    117.     "Class Code""",  
    118.     "Caption""TST, INSP OF D/E Frequency Low [1]",  
    119.     "Dept""ENG",  
    120.     "Rank""ETO",  
    121.     "ID""00922",  
    122.     "Interval""6 M",  
    123.     "Date/ Hours""11/14/2016",  
    124.     "Action"""  
    125. });  
    126. data.push({  
    127.     "Status": [{  
    128.         "val""Overdue",  
    129.         "color""label label-danger"  
    130.     }],  
    131.     "Start Date""2017-05-24",  
    132.     "End Date""2017-05-26",  
    133.     "Critical""true",  
    134.     "CSM""false",  
    135.     "E0/EC0""true",  
    136.     "Component""Boiler Fo Booster Pump Stbd",  
    137.     "Class Code""",  
    138.     "Caption""OVH, INSP OF Boiler Fo Booster Pump Stbd",  
    139.     "Dept""ENG",  
    140.     "Rank""2E",  
    141.     "ID""00470",  
    142.     "Interval""30 M",  
    143.     "Date/ Hours""5/6/2017",  
    144.     "Action"""  
    145. });  
    146. data.push({  
    147.     "Status": [{  
    148.         "val""Overdue",  
    149.         "color""label label-danger"  
    150.     }],  
    151.     "Start Date""2017-05-14",  
    152.     "End Date""2017-05-26",  
    153.     "Critical""false",  
    154.     "CSM""false",  
    155.     "E0/EC0""true",  
    156.     "Component""Boiler Safety Valve",  
    157.     "Class Code""",  
    158.     "Caption""OVH, INSP OF Boiler Safety Valve",  
    159.     "Dept""ENG",  
    160.     "Rank""3E",  
    161.     "ID""00473",  
    162.     "Interval""12 M",  
    163.     "Date/ Hours""9/23/2016",  
    164.     "Action"""  
    165. });  
    166. data.push({  
    167.     "Status": [{  
    168.         "val""Due",  
    169.         "color""label label-success"  
    170.     }],  
    171.     "Start Date""2017-05-29",  
    172.     "End Date""2017-05-14",  
    173.     "Critical""false",  
    174.     "CSM""false",  
    175.     "E0/EC0""true",  
    176.     "Component""Air Condition Condenser",  
    177.     "Class Code""",  
    178.     "Caption""TST, INSP OF Air Condition Condenser",  
    179.     "Dept""ENG",  
    180.     "Rank""2E",  
    181.     "ID""00554",  
    182.     "Interval""30 M",  
    183.     "Date/ Hours""6/1/2017",  
    184.     "Action"""  
    185. });  
    186. data.push({  
    187.     "Status": [{  
    188.         "val""Overdue",  
    189.         "color""label label-danger"  
    190.     }],  
    191.     "Start Date""2017-05-11",  
    192.     "End Date""2017-05-29",  
    193.     "Critical""false",  
    194.     "CSM""false",  
    195.     "E0/EC0""true",  
    196.     "Component""Sludge Pump",  
    197.     "Class Code""",  
    198.     "Caption""OVH, INSP OF Sludge Pump",  
    199.     "Dept""ENG",  
    200.     "Rank""2E",  
    201.     "ID""00588",  
    202.     "Interval""30 M",  
    203.     "Date/ Hours""5/22/2017",  
    204.     "Action"""  
    205. });  
    206. data.push({  
    207.     "Status": [{  
    208.         "val""Overdue",  
    209.         "color""label label-danger"  
    210.     }],  
    211.     "Start Date""2017-05-13",  
    212.     "End Date""2017-05-11",  
    213.     "Critical""false",  
    214.     "CSM""false",  
    215.     "E0/EC0""true",  
    216.     "Component""Bilge Filters",  
    217.     "Class Code""",  
    218.     "Caption""CLN, INSP OF Bilge Filters",  
    219.     "Dept""ENG",  
    220.     "Rank""2E",  
    221.     "ID""00589",  
    222.     "Interval""1 M",  
    223.     "Date/ Hours""9/5/2016",  
    224.     "Action"""  
    225. });  
    226. data.push({  
    227.     "Status": [{  
    228.         "val""Overdue",  
    229.         "color""label label-danger"  
    230.     }],  
    231.     "Start Date""2017-05-11",  
    232.     "End Date""2017-05-14",  
    233.     "Critical""false",  
    234.     "CSM""false",  
    235.     "E0/EC0""true",  
    236.     "Component""Emergency Bilge Suction - Er",  
    237.     "Class Code""",  
    238.     "Caption""TST, INSP OF Emergency Bilge Suction - Er",  
    239.     "Dept""ENG",  
    240.     "Rank""2E",  
    241.     "ID""00591",  
    242.     "Interval""1 M",  
    243.     "Date/ Hours""9/5/2016",  
    244.     "Action"""  
    245. });  
    246. data.push({  
    247.     "Status": [{  
    248.         "val""Overdue",  
    249.         "color""label label-danger"  
    250.     }],  
    251.     "Start Date""2017-05-14",  
    252.     "End Date""2017-05-13",  
    253.     "Critical""false",  
    254.     "CSM""false",  
    255.     "E0/EC0""true",  
    256.     "Component""Hydraulic For Operating Valve System",  
    257.     "Class Code""",  
    258.     "Caption""ANL, INSP OF Hydraulic For Operating Valve System",  
    259.     "Dept""ENG",  
    260.     "Rank""2E",  
    261.     "ID""00594",  
    262.     "Interval""6 M",  
    263.     "Date/ Hours""12/2/2016",  
    264.     "Action"""  
    265. });  
    266. $rootScope.gridData = eval(data);  
    267. });   
  • Here, we have static JSON data in the same way you do with the db data.
  • Data is in the form of array objects.
  • In every column object, we have multiple key value pairs.
  • In the object showTags, the key is used to merge multiple boolean columns into one column as tags.
  • showColumns is used for show and hide of columns.
  • Other keys serve the same purpose as the name given to them.
  • $rootScope is available globally in the whole application that is we can set rootscope in 1 controller and access the value in other controller with rootscope.
  • we store the array of columns in $scope.columns and array of data in $rootScope.gridData.
  • We are going to access these in View for binding of data.
In the Index view of home controller, start writing the following code. 
  1. <html ng-app = "myApp">
  2. <body>
  3. <div class="table-responsive" ng-controller="gridController">  
  4.    <table class="table table-striped table-bordered table-hover dataTables-example">  
  5.       <thead>  
  6.          <tr>  
  7.             <th ng-repeat="column in columns" width="{{column.width}}" ng-if="column.showColumns == 'true' && column.dataType != 'commands' && column.dataType != 'bool'">  
  8.                <b>{{column.key}}</b>  
  9.             </th>  
  10.             <th ng-repeat="column in columns" ng-if="column.dataType == 'bool' && column.showColumns=='true'" width="5%">Tags</th>  
  11.             <th aria-sort="descending" ng-repeat="column in columns" width="{{column.width}}" ng-if="column.showColumns == 'true' && column.dataType == 'commands'">{{column.key}}</th>  
  12.          </tr>  
  13.       </thead>  
  14.       <tbody>  
  15.          <tr ng-class="{'primaryRow':rowIndex===key}" data-ng-repeat="(key,val) in gridData">  
  16.             <td ng-repeat="column in columns" class="project-status" ng-if="column.dataType== 'status' && column.showColumns == 'true'">  
  17.                <span ng-repeat="col in column" ng-class="val[col][0].color">{{val[col][0].val}}</span>                                             
  18.             </td>  
  19.             <td ng-repeat="column in columns" class="project-title" ng-if="column.dataType == 'string' && column.showColumns == 'true'">{{val[column.key]}}  
  20.             </td>  
  21.             <td ng-repeat="column in columns" class="project-title" ng-if="column.dataType == 'date' && column.showColumns == 'true'" style="text-align: right;">{{val[column.key]}}  
  22.             </td>  
  23.             <td ng-repeat="column in columns" class="project-title" ng-if="column.dataType == 'check' && column.showColumns == 'true'">  
  24.                <input type="checkbox" ng-checked="{{val[column.key]}}" disabled />  
  25.             </td>  
  26.             <td class="project-title">  
  27.                <span id="tagSpan" ng-if="column.showTags == 'true' && val[column.key] == 'true'" ng-repeat="column in columns" class="label label-default">{{column.key}}</span>  
  28.                <span ng-hide="true">{{val[column.key]}}</span>  
  29.             </td>  
  30.             <td ng-repeat="column in columns" ng-if="column.key == 'Action'">  
  31.                <a>@Html.ActionLink("View", "ActionName", "ControllerName", new { @class = "btn btn-xs btn-success" })</a>  
  32.             </td>  
  33.          </tr>  
  34.       </tbody>  
  35.    </table>  
  36. </div> 
  37. </body>
  38. </html>
  • Put ng-app directive on html tag and ng-controller on div tag.
  • Here in the view we created key value pairs.
  • We automized the entire grid without hardcoding the name of single column in grid.
  • We use ng-repeat for automizing the entire json.

    • Columns are created by putting ng-repeat on th. Example : <th ng-repeat = "column in Columns">column.key</th>.
    • Show and hide the columns by putting column.showColumns key on tags.
    • We also put multiple conditions and set different styles by iterating.
    • It iterates as many times as number of keys in $scope.columns.
    • Similarly row data are created by iterating $scope.gridData with column key.Example : <tr ng-repeat="(key,val) in gridData"><td ng-repeat="column in Columns"> val[column.key]</td></tr>.
    • Include scripts in bundle config.cs.
  1. bundles.Add(new ScriptBundle("~/bundles/angular").Include(  
  2.                 "~/Scripts/angular1.5.5.min.js",  
  3.                 "~/Scripts/Module.js",  
  4.                 "~/Scripts/Controller.js"));  
  • Add this bundle in RegisterBundle method in BundleConfig.cs file.
  • Include bundle on layout page as given below.
  1. @Scripts.Render("~/bundles/jquery")  
  2. @Scripts.Render("~/bundles/bootstrap")  
  3. @Scripts.Render("~/bundles/angular") 

Now, run the application and get the result.