Most of you already know that I still like my WebForms. People have argued that using AngularJS with WebForms is pointless, but I say NA! It makes the user experience a little bit smoother.
In this blog I will show you how to create a table that can be sorted and paged using AngularJS. I chose not to use a webserivce as I did not feel like this warranted the extra overhead and code. I wanted to keep this absolutely simple. I would have used a webserivce had I been creating an API for others to use. This is also a project that is ultimately using WebForms, had I been doing an MVC project; webservices would have been a better choice.
Is this the best way; probably not! This is my first run with this, so I am doing it the way I know and the way I find the easiest to manipulate for my purpose.
This is a simple example that most people would know. How to build a data string to be used in our AngularJS controller. There is nothing of rocket science here, but it is required to show the first piece of the puzzle.
SqlDataReader rdr = cmd.ExecuteReader();
data = "[";
while (rdr.Read())
{
if (data.Length > 1) data += ",\n";
data += "{";
data += String.Format("FirstName:'{0}', LastName:'{1}', Email:'{2}', id:'{3}'", rdr["first_name"], rdr["last_name"], rdr["email"], rdr["id"]);
data += "}";
}
data += "]";
This is a pretty common way to render dynamic data… I create an ASPX form page with absolutely no content. No tags at all. All that remains is the Page tag that links the code behind. I do this for images, PDF, CSV files and more. The code behind is what does the grunt work. It creates the output and pushes it through the response object. Effectively we cancel the default headers and create new headers telling the browser that we are now a different file type. In this case a plain/text file. The browser will see this as a JavaScript file based on our HTML implementation later in this blog.
public partial class TableData : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
String data = U_University.Lib.User.GetAllUsersData();
String script = @"
var app = angular.module('users', ['ngTable']).
controller('UsersController', function ($scope, $filter, NgTableParams) {
data=" + data + @";
$scope.tableParams = new NgTableParams({
page: 1, // show first page
count: 10, // count per page
sorting: {
name: 'asc' // initial sorting
}
}, {
total: data.length, // length of data
getData: function($defer, params) {
// use build-in angular filter
var orderedData = params.sorting() ?
$filter('orderBy')(data, params.orderBy()) :
data;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
})";
Response.ClearHeaders();
Response.ClearContent();
Response.ContentType = "text/plain";
Response.Output.Write(script);
}
}
In the header of my HTML file, I establish my includes. All of the “.js” can easily be found with a Google search. You need the angular.js, ng-table.js and the ng-table.css files for this example. The key to my controller and its data is within the following tag:
<script src=”TableData.aspx” type=”text/javascript”></script>
This tag is referencing my empty page the hijacks the response object and outputs my controller containing my dynamic data.
<script src="/js/angular.js" type="text/javascript"></script>
<script src="/js/angular-sanitize.js" type="text/javascript"></script>
<script src="/js/ng-table.js" type="text/javascript"></script>
<script src="TableData.aspx" type="text/javascript"></script>
<link href="/css/ng-table.css" rel="stylesheet" type="text/css" />
Now to setup my table. I am using the ng-table.js library. This allows me to create a sortable and pageable table fairly easily. There is really nothing too fancy, just some additional attributes (data-title, sortable). Everything else in the table is standard HTML/AngularJS.
<div ng-app="users" ng-controller="UsersController">
<div class="text-center"><h1>User Manager</h1></div>
<form id="frmMain" runat="server">
<div class="text-right"><asp:LinkButton runat="server" ID="lnkNew">New User</asp:LinkButton></div>
<table ng-table="tableParams" class="table">
<tr ng-repeat="user in $data">
<td data-title="'First Name'" sortable="'FirstName'"><a href="AddEdit.aspx?id={{user.id}}">{{user.FirstName}}</a></td>
<td data-title="'Last Name'" sortable="'LastName'">{{user.LastName}}</td>
<td data-title="'Email'" sortable="'Email'">{{user.Email}}</td>
</tr>
</table>
</form>
</div>
VOILA! We now have a sortable, pageable table – and it looks pretty as well!