Wednesday, May 21, 2014

Angular JS - Another Tool in your XPages Toolbox - Part 2

In my previous post, I shared my reason for wanting to try to learn how to use Angular within an XPage.  In this post, I will show you how I used Angular to duplicate the functionality of a Dojo data grid on the same page.

My Existing XPage

In my existing XPage, I use the Extension Library REST service control to return data based on what the current user has rights to see.  The REST service use a formula for "keys" which filters the data based on the first column.  The REST service outputs JSON which is read by the Dojo Data Grid.
Dojo DataGrid 
There are two thing that have always bugged me about the Dojo grid that I created.  The first was that I could never get column sorting to work.  It seemed to have a conflict with the user of the keys property that I could not overcome.  The second thing that bugged me was that I could not get the grid to behave in a responsive manner.  When I shrink the screen, the Dojo grid would not shrink with it. I accept that it is possible that in both cases I was doing something wrong there, but I did spend a lot of time trying to get those things to work.

Grid using Angular

Since I duplicating what I did with Dojo, I used an Angular plug-in called ng-grid.  I used the very same JSON data to display the grid inside a <div>.
Grid using Angular
The Angular Grid not only looks good, but the column sorting works as well.  This grid is naturally responsive and solves my two big gripes with the Dojo grid. 

Look, I'm responsive

The 'How To' Section

Before I go through my steps, let me say that this is not a beginners guide to Angular, to really understand it.
There is a lot of information out on the web on Angular. I highly recommend Mark Roden's latest series on Angular which takes a methodical approach that is easy to follow.

1)  First you have to load the library on your page.  After downloading Angular from Google, I copied the library in a folder I created under the "Web Content" subdirectory.

2)  I then referenced the library using a <script> tag in only the page where I used Angular.  Use Firebug to check that you loaded everything correctly.
3) I then create a Controller file and call it grid-controller and place it is a subdirectory under the "Angular" folder under "Web Content".   Repeat step 2 for the controller file, making sure to account for the subdirectory in your script tag.

4) Normally for a page using Angular, you will add an attribute to the <html> tag of "ng-app" telling Angular that you are using it on the whole page.   In my case, I added the "ng-app" attribute to a <div> on my page.  I actually used a <xp:panel>, and set the tagName to render as a <div>. I did it this way because I wanted to show how you would use an XPage control where you also decide whether to render the grid based on certain conditions.  The easiest route though, is to pass HTML through like in the second example below.

This is all the code needed on the custom control.  Note: Once div is nested in the other.
This is how it would look if you pass the HTML straight through

5) Angular also needs you to specify the name of the Controller to use for a specific element.  A normal Angular application might use several controllers throughout the page to connect the data to the display.  You tell Angular which one for a specific section by using the ng-controller attribute. In my case, I am only using a single controller that I set in the same <div>.  Besides setting the style, that is all I have on the custom control.

6)  In my controller, I need to tell where to get the model (data) to send to the view (XPage).  As I stated above, I am using the same JSON data as the Dojo Grid.  To access the JSON, I use $http.get() method to read the URL of my REST Service.  Remember, you can the pathInfo attribute in your REST service, which allows you to see the JSON in a URL. I set my pathInfo to "restData".  The result is set to a variable called $scope, which acts as your return value of the controller.

The Controller which in Angular connects the data and the display
From line 8 to the end is specific to the ng-grid plug-in which I explain below. Everything outlined up to this point is all you need to test out Angular in your XPage.  Before I added the grid to my demo, I was able to display the whole list using ng-repeat. I was also able to reference the data is $scope using direct references like this {poDoc[0].Status}}  The controller returns an array in this case. I could have done anything you can do in Angular to the data. I encourage you to give it a try.

The last part of the code refines the $scope to sets options and format for the grid.  In order to get the grid to work it had to be in its own <div> that was a child of the <div> where I set the ng-app and ng-controller.  The grid is not part of core Angular so in order to use it I did had to download and a separate javascript and css file. To find ng-grid look here, note that it has a dependency on jQuery. It gets a thumbs up in my book.

Where to from here

I am really intrigued by Angular, so I will continue to experiment with it.  Next, I would like to enhance the example here to allow the grid to launch documents and perform searching/filtering.  If the result is worth sharing then I will make a part 3 of this series.

No comments:

Post a Comment