Provider Hosted MVC App With AngularJS In SharePoint - Part 3

This article is continuation of Part-1 & Part-2.

Let's start with Provider Hosted MVC App with AngularJS - Part 3. In this part we are going to create dynamic TileView using CSS and AngularJS.

SharePoint HostWeb List Structure


The following is a list structure which we are referencing for our application.



Figure 1: App

We are going to create the following UI Design and final output format.

UI Change

In top navigation bar new option added to show tileview i.e. TileView.



Figure 2: Tile

Output



Figure 3: output

Solution Changes in term of new controller, view , javascript and CSS files.



Figure 4: Solution

Let's start with service layer coding to fetch list data.

Step 1: Session Management in AngularJS

When we navigate from one page to another page, we need ' hostweburl ' & ' appweburl ' URL values to access SharePoint site data, so we need to save those values in session to access on another page.

There are two ways to save data in session - sessionStorage & localStorage.
  1. var hostweburl;    
  2. var appweburl;    
  3.     
  4. //The SharePoint App where the App is actualy installed    
  5. hostweburl = decodeURIComponent(QueryStringParameter('SPHostUrl'));    
  6.     
  7. //The App web where the component to be accessed by the app are deployed    
  8. appweburl = decodeURIComponent(QueryStringParameter('SPAppWebUrl'));    
  9.     
  10. var Sessionhostweburl = sessionStorage.getItem("hostweburl");    
  11. var Sessionappweburl = sessionStorage.getItem("appweburl");    
  12.     
  13. if (Sessionhostweburl == null || Sessionappweburl == null)
  14. {    
  15.     sessionStorage.setItem("hostweburl", hostweburl);    
  16.     sessionStorage.setItem("appweburl", appweburl);    
  17. }    
  18.     
  19. if (hostweburl == null || appweburl == null || hostweburl == 'undefined' || appweburl == 'undefined')
  20. {    
  21.     hostweburl = sessionStorage.getItem("hostweburl");    
  22.     appweburl = sessionStorage.getItem("appweburl");    
  23. }    
  24.     
  25. console.log("hostweburl : " + hostweburl);    
  26. console.log("appweburl : " + appweburl);   

app-data-service.js

New service layer method to get SharePoint List data in order to create TileView.

  1. this.getTileData = function()   
  2. {  
  3.   
  4.     var TileArray = [];  
  5.   
  6.     var deferred = $q.defer();  
  7.   
  8.     // Load 15hives js files and continue to the successHandler  
  9.     $.getScript(scriptbase + "SP.Runtime.js",  
  10.   
  11.     function()   
  12.     {  
  13.         $.getScript(scriptbase + "SP.js",  
  14.   
  15.         function()  
  16.         {  
  17.             $.getScript(scriptbase + "SP.RequestExecutor.js",  
  18.   
  19.             function()  
  20.             {  
  21.   
  22.                 //Represents the context for objects and operations.  
  23.                 var context = new SP.ClientContext(appweburl);  
  24.   
  25.                 //Access host web from app using JavaScript CSOM  
  26.                 var factory = new SP.ProxyWebRequestExecutorFactory(appweburl);  
  27.                 context.set_webRequestExecutorFactory(factory);  
  28.   
  29.                 var appContextSite = new SP.AppContextSite(context, hostweburl);  
  30.                 var web = appContextSite.get_web();  
  31.                 context.load(web);  
  32.   
  33.                 //Access HostWeb List  
  34.                 var list = web.get_lists().getByTitle('lstTileLinks');  
  35.   
  36.                 var camlQuery = SP.CamlQuery.createAllItemsQuery();  
  37.                 this.listItems = list.getItems(camlQuery);  
  38.                 context.load(this.listItems);  
  39.   
  40.                 context.executeQueryAsync(  
  41.                 Function.createDelegate(this, function()   
  42.                 {  
  43.   
  44.                     var ListEnumerator = this.listItems.getEnumerator();  
  45.   
  46.                     while (ListEnumerator.moveNext())  
  47.                     {  
  48.   
  49.                         var currentItem = ListEnumerator.get_current();  
  50.                         TileArray.push({  
  51.                             ID: currentItem.get_item('ID'),  
  52.                             Title: currentItem.get_item('Title'),  
  53.                             TileURL: currentItem.get_item('TileURL')  
  54.                         });  
  55.                     }  
  56.   
  57.                     console.log(TileArray);  
  58.                     deferred.resolve(TileArray);  
  59.                 }),  
  60.                 Function.createDelegate(this, function(sender, args) {  
  61.                     deferred.reject('Request failed. ' + args.get_message());  
  62.                     console.log("Error : " + args.get_stackTrace());  
  63.                 }));  
  64.             });  
  65.         });  
  66.     });  
  67.   
  68.     return deferred.promise;  
  69. }; // Get 

app-tile-controller.js

New controller added into solution for TileView creation.
  1. (function()   
  2. {  
  3.   
  4.     console.log('app-tile-controller.js loaded ..');  
  5.     'use strict'  
  6.   
  7.     angular.module(window.AngularApp_constants.architecture.modules.MainApp.moduleKey)  
  8.         .controller('TileController', HomeController)  
  9.   
  10.     HomeController.$inject = ['$scope''$location''app-data-service'];  
  11.   
  12.     function HomeController($scope, $location, AngularDataService)   
  13.     {  
  14.   
  15.         /********* Fill Tile *********/  
  16.         $scope.TileMaster = [];  
  17.   
  18.         LoadTileData();  
  19.   
  20.         function LoadTileData()   
  21.         {  
  22.   
  23.             console.log("LoadTileData called");  
  24.   
  25.             var promiseGet = AngularDataService.getTileData();  
  26.             promiseGet.then(function(resp)   
  27.             {  
  28.                 $scope.TileMaster = resp;  
  29.             },   
  30.             function(err)  
  31.             {  
  32.                 $scope.Message = "Error " + err.status;  
  33.                 console.log($scope.Message);  
  34.             });  
  35.         }  
  36.     }  
  37.   
  38. })(); 

TileMasterController

New controller added into solution for tile creation.
  1. public class TileMasterController: Controller   
  2. {  
  3.     // GET: TileMaster  
  4.     public ActionResult TileMaster()   
  5.     {  
  6.         return View();  
  7.     }  

TileMaster.cshtml

  1. @{  
  2. ViewBag.Title = "Home Page";  
  3. }  
  4. <!-- Javascript from hives Layout folder -->  
  5. <script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>  
  6. <script type="text/javascript" src="/_layouts/15/sp.js"></script>  
  7. <script type="text/ecmascript" src="/_layouts/SP.Core.js"></script>  
  8. <script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js"></script>  
  9. <!-- Basic JS Files -->  
  10. <script src="~/AngularJSScript/BasicJS/angular.min.js"></script>  
  11. <script src="~/AngularJSScript/BasicJS/trNgGrid.js"></script>  
  12. <script src="~/AngularJSScript/BasicJS/angular-messages.js"></script>  
  13. <!-- Custom JS Files -->  
  14. <script src="~/AngularJSScript/CustomJS/app-constants.js"></script>  
  15. <script src="~/AngularJSScript/CustomJS/app-main.js"></script>  
  16. <script src="~/AngularJSScript/CustomJS/app-data-service.js"></script>  
  17. <script src="~/AngularJSScript/CustomJS/app-tile-controller.js"></script>  
  18. <link href="~/Content/TileBranding.css" rel="stylesheet" />  
  19. <div ng-app="AngularApp">  
  20.     <div ng-controller="TileController">  
  21.         <br />  
  22.         <br />  
  23.         <ul>  
  24.             <li ng-repeat="Tile in TileMaster">  
  25.                 <div class="ActiveTile">  
  26.                     <div class="TileHeading">  
  27.                         <a href="{{ Tile.TileURL }}" target="_blank">{{ Tile.Title }} </a>  
  28.                     </div>  
  29.                 </div>  
  30.             </li>  
  31.         </ul>  
  32.     </div>  
  33. </div>  

TileBranding.css

  1. .ActiveTile {    
  2.     display: inline-block;    
  3.     position: relative;    
  4.     width: 250px;    
  5.     height: 150px;    
  6.     /*background: #ccffcc;*/    
  7.     background-color: rgb(0, 179, 125);    
  8.     z-index: 0;    
  9.     margin: 15px 40px 2px -2px;    
  10.     transition: all .15s ease-in-out;    
  11. }    
  12.     
  13.     .ActiveTile:hover {    
  14.         /*background: #9CC;*/    
  15.         background-color: #00CC66;    
  16.         z-index: 100;    
  17.         /*transform: scale(1.2,1.2);*/    
  18.         box-shadow: 0 5px 10px 0 rgba(0,0,0,.2);    
  19.     }    
  20.     
  21. .TileHeading {    
  22.     color: powderblue;    
  23.     font-size:20px;    
  24.     margin: 63px 10px 10px 60px;    
  25. }    
  26. /************************************/    
  27.     
  28. ul, li {    
  29.     list-style: none;    
  30.     margin: 0;    
  31.     padding: 0;    
  32.     display: inline;    
  33. }    
  34.     
  35. a {    
  36.     display: block;    
  37.     width: 100%;    
  38.     height: 100%;    
  39.     text-decoration: none !important;    
  40.     color: white;    
  41.     font-size: 18px;    
  42. }   

I hope you all liked this article as you liked the Part 1 and Part 2 of the series..

Thank you!