Skip to main content

The Conversion: Lay of the Landing Page - Part 3

In Part 1 of Lay of the Landing Page, the basic landing page framework was established.  In Part 2, the table was added as well as some AngularJS filtering capability.  For Part 3, the participant count, column sorting and routing to the trip edit and detail page will be developed.

The participant count is fairly straight forward to get as it is just a count of records in the trip_persons table. The more difficult part is determining who completed the required documentation.  Fortunately, because this is conversion project, the code already exists to get this data.

Since college sponsored trips mostly revolve around the students, the participant count on the landing page will be the number of students on the trip. But when user drills down into a trip, a breakdown of all participants will be displayed.

With the Students column (student participant count) added, we can see that the table is getting a little crowded. There are three options: reduce the number of columns; or condense the table; or both. In this case, after seeing the Type listed, I don't think it's necessary to have on the landing page. So for now, it will get removed - but we'll keep the data as part of the JSON just in case.

For column sorting, I suspect the user may want to sort by Trip Name, Destination, Departure and Arrival.  To do the sorting, I am going to leverage the orderBy clause in the ng-repeat directive. The first thing to do is create sortType and sortReverse variables in the controller.  "sortType" will be the field that's going to be ordered and sortReverse is a boolean - if it is false, the sort will be ascending.  And then the following pattern will be repeated for each column that is sortable.

 <a href="#" ng-click="sortType = 'fieldNameGoesHere'; sortReverse = !sortReverse">  
     fieldTitleGoesHere
     <span ng-show="sortType == 'fieldNameGoesHere' && sortReverse" class="glyphicon glyphicon-triangle-bottom"></span>  
     <span ng-show="sortType == 'fieldNameGoesHere' && !sortReverse" class="glyphicon glyphicon-triangle-top"></span>  
 </a>  
Now I am sure there are table plug-ins out there that can do the same thing, but this is an easy implementation.
The last item for this post is adding some navigation from the landing page to a trip detail page. Adding an icon to the left of the trip name should suffice as a visual reference to the user to get more detail. At this stage of the game, the landing template looks like following:
 <div ng-controller="LandingController as ctrlLanding">  
   <h3>TRIPS</h3>  
   <div class="alert alert-info">Welcome to the Travel Resource Information Planning System (TRIPS).</div>  
   <div class="input-group">  
     <span class="input-group-addon">Filter</span>  
     <input class="form-control" ng-model="tripFilter"></input>  
   </div>  
   <table class="table">  
     <tr><th></th>  
       <th><a href="#" ng-click="sortType = 'NAME'; sortReverse = !sortReverse">  
           Trip Name  
           <span ng-show="sortType == 'NAME' && sortReverse" class="glyphicon glyphicon-triangle-bottom"></span>  
           <span ng-show="sortType == 'NAME' && !sortReverse" class="glyphicon glyphicon-triangle-top"></span>  
         </a>  
       </th>  
       <th><a href="#" ng-click="sortType = 'DESTINATION'; sortReverse = !sortReverse">  
           Destination  
           <span ng-show="sortType == 'DESTINATION' && sortReverse" class="glyphicon glyphicon-triangle-bottom"></span>  
           <span ng-show="sortType == 'DESTINATION' && !sortReverse" class="glyphicon glyphicon-triangle-top"></span>  
         </a>  
       </th>  
       <th class="text-center">Students</th>  
       <th><a href="#" ng-click="sortType = 'OUTBOUNDDEPARTURE'; sortReverse = !sortReverse">  
           Departure  
           <span ng-show="sortType == 'OUTBOUNDDEPARTURE' && sortReverse" class="glyphicon glyphicon-triangle-bottom"></span>  
           <span ng-show="sortType == 'OUTBOUNDDEPARTURE' && !sortReverse" class="glyphicon glyphicon-triangle-top"></span>  
         </a>  
       </th>  
       <th><a href="#" ng-click="sortType = 'INBOUNDARRIVAL'; sortReverse = !sortReverse">  
           Arrival  
           <span ng-show="sortType == 'INBOUNDARRIVAL' && sortReverse" class="glyphicon glyphicon-triangle-bottom"></span>  
           <span ng-show="sortType == 'INBOUNDARRIVAL' && !sortReverse" class="glyphicon glyphicon-triangle-top"></span>  
         </a>  
       </th>  
     </tr>  
     <tr ng-repeat="trip in trips | filter: filterTrips | orderBy: sortType:sortReverse">  
       <td><a ui-sref="trip({id: trip.ID})"><span class="glyphicon glyphicon-circle-arrow-right"></span></a></td>  
       <td>{{trip.NAME}}</td>  
       <td>{{trip.DESTINATION}}</td>  
       <td class="text-center">{{trip.PARTICIPANTCOUNT}}</td>  
       <td>{{trip.OUTBOUNDDEPARTURE}}</td>  
       <td>{{trip.INBOUNDARRIVAL}}</td>  
     </tr>  
   </table>  
 </div>  
The landing controller hasn't seen much change from last time - just the addition of the two $scope variables to keep track of ordering.
 angular.module('core').controller('LandingController',['$scope','dataService', function($scope,dataService){  
   $scope.trips = [];  
   $scope.tripFilter = '';  
   $scope.sortType = 'NAME';  
   $scope.sortReverse = false;  
   dataService.call('getTrips').then(function(data){  
     $scope.trips = data.data;  
   })  
   $scope.filterTrips = function(_item){  
     var _r = false;  
     if (  _item.NAME.toLowerCase().indexOf($scope.tripFilter.toLowerCase()) > -1 ||  
         _item.DESTINATION.toLowerCase().indexOf($scope.tripFilter.toLowerCase()) > -1 ||  
         $scope.tripFilter.length == 0 ) {  
       _r = true;  
     }  
     return _r;  
   }  
 }]);  
To prepare for the trip details page and satisfy the link that was added to the landing page for each trip row, the routers.js has been updated.

 angular.module('core').config(function($stateProvider, $urlRouterProvider) {  
   $urlRouterProvider.otherwise("/trips/landing");  
   $stateProvider  
     .state('landing', {url: "/trips/landing", templateUrl: "apps/trips/templates/landing.html"})  
     .state('trip', {url: "/trips/trip/:id", templateUrl: "apps/trips/templates/trip.html"})  
 });  

Note that the new trip route has a :id at the end of the url string. This is the placeholder for the id that is sent over view the ui-sref="trip({id: trip.ID})" directive in the link to the trip.

Tabled for this post is the checking to see how many participants completed their contact and waiver information. I will revisit this - I am thinking that I can color code the participant number as indicator that there are students missing the required information.

Hope you find these posts informational. Cheers!

Comments

Popular posts from this blog

The Conversion: MAIN.CFM

Within the current development pattern I have for our portal system, the main.cfm is the starting point for an application. For the most part, this is really boilerplate and serves to get the application off the ground. The way the portal works is that the user lands on the main menu page and provide with a menu of options. Each option is called a function and is assigned a unique id. When the user clicks on a menu option, the page is reloaded with the function id. The process checks to see if the user is actually allowed to have access to the function. It then accordingly looks up the path and displays the page via a . In the case of the TRIPS application, the included file is the main.cfm page for the application. So far the project looks like this: we have the folder structure defined with no files aside from the main.cfm. The main.cfm contains a few javascript includes, the overarching controller for the application as well as the route viewer. The next blog post will foc...

The Conversion: Lay of the Landing Page - Part 1

In the last post  the groundwork has been laid for real development to begin. The data service, router, and landing pages have been created and are ready for code. The last thing to add for this part of the process is the Coldfusion component. A data folder has been added to store any cfcs relevant to the TRIPS application. The first is to write the CFFUNCTION that will return the list of trips. My development pattern for creating CF functions is fairly routine.  First, decide on a name, parameters and return type.  Sometimes the naming of a function is the hardest part.  I've settled on actionDataObject.  So in this case, the function will be named: getTrips.    At moment, the landing controller (landing.js) is empty. angular.module('core').controller('LandingController',['$scope','dataService', function($scope,dataService){ }]); The basic task of this controller is getting the list of trips.  First is the establishment of an empty tr...

Dynamically Loading an AngularJS UI.Router

When starting out on my AngularJS journey, I couldn't get a good handle on the router native to the framework. So I adopted the use of the wonderful angular-ui / ui-router.  During the past few years of development, I've honed in (for better or worse) my paradigm for setting new applications and nearly every AngularJS app has a routes.js file. Without going into background, I wanted a way to load the ui-router dynamically. Typically, the routes gets defined in a .js file and typically looks something like this: angular.module('core').config(function($stateProvider, $urlRouterProvider) { $urlRouterProvider.otherwise("/landing/201820"); $stateProvider .state('landing', {url: "/landing/:term", templateUrl: "apps/noted/templates/landing.html"}) .state('uploadCalendar', {url: "/uploadCalendar", templateUrl: "apps/noted/templates/uploadCalendar.html"}) .state('noteTakers...