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.