<< Back

Instructions for Completing the Campus Travel Mobile App Project with Ionic Creator Pro

In this project you are going to finish a mobile app version of the Campus Travel website like this.

Click for a video on completing this exercise.

We assume you have completed Campus Travel Part 1. Click if you want to complete Part 2 without upgrading to the Pro version.

Open Ionic Creator to your Campus Travel project.

Add Angular Directives to Pages

1. Agent Bookings
  1. In the Pages panel, click to open the Agent Bookings page.
  2. Click and make sure you have the second div row container selected.
  3. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-repeat with value booking in bookings
2. Sales
  1. In the Pages panel, click to open the Sales page.
  2. Click and make sure you have the second div row container selected.
  3. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-repeat with value sale in sales
3. Add Agent
  1. In the Pages panel, click to open the Add Agent page.
  2. Click to select the Agent Name Input component.
  3. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-model with value data.agent
  4. Click to select the Office Select component.
  5. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-model with value data.office
  6. Add another Angular Directive ng-options with value office.OfficeID as office.OfficeLocation for office in offices
  7. Click to select the Button component.
  8. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-click with value addAgent()
  9. Add another Angular Directive ng-hide with value hideButton
4. Add Sale
  1. In the Pages panel, click to open the Add Sale page.
  2. Click to select the Agent Select component.
  3. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-model with value data.agent
  4. Add another Angular Directive ng-options with value agent.AgentID as agent.AgentName for agent in agents
  5. Click to select the Sale Date Input component.
  6. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-model with value data.saleDate
  7. Click to select the Destination Select component.
  8. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-model with value data.destination
  9. Add another Angular Directive ng-options with value destination.DestinationID as destination.DestinationName for destination in destinations
  10. Click to select the Amount Input component.
  11. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-model with value data.amount
  12. Click to select the Button component.
  13. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-click with value addSale()
  14. Add another Angular Directive ng-hide with value hideButton
5. Update Sale
  1. In the Pages panel, click to open the Update Sale page.
  2. In Properties panel for the page, add a Route Parameter with Param name: saleId and a default value of 1
  3. Click to select the Delete Button component.
  4. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-click with value deleteSale()
  5. Add another Angular Directive ng-hide with value hideDeleteButton
  6. Click to select the Agent Select component.
  7. Above the Properties panel on the right, click Form to select the outer container that holds the four form components.
  8. Add an Angular Directive ng-hide with value hideUpdateForm
  9. (Also, make sure the paragraph tag above the form contains {{ post.message }}.)
  10. Click again to select the Agent Select component.
  11. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-model with value data.agentKey
  12. Add another Angular Directive ng-options with value agent.AgentID as agent.AgentName for agent in agents
  13. Click to select the Sale Date Input component.
  14. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-model with value data.saleDate
  15. Click to select the Amount Input component.
  16. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-model with value data.amount
  17. Click to select the Destination Select component.
  18. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-model with value data.destinationKey
  19. Add another Angular Directive ng-options with value destination.DestinationID as destination.DestinationName for destination in destinations
  20. Click to select the Update Button component.
  21. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-click with value updateSale()
  22. Add another Angular Directive ng-hide with value hideUpdateButton
6. Search Results
  1. In the Pages panel, click to open the Search Results page.
  2. In Properties panel for the page, add a Route Parameter with Param name: agent and a default value of 0
  3. Add another Route Parameter with Param name: destination and a default value of 0
  4. Add another Route Parameter with Param name: above and a default value of 0
  5. Add another Route Parameter with Param name: below and a default value of 0
  6. Click and make sure you have the second div row container selected.
  7. Under Angular Directives, add Angular Directive ng-repeat with value sale in sales
  8. Click to select the Button component.
  9. You will notice that the button is linked to Update Sale - /page9. Since there is a Route Input parameter now declared for the Update Sale page,
    you will notice under the link page is a text box to specify a value for the SaleID that must be passed into the Update Sale page.
    Enter {{ sale.SaleID }} in the text box for SaleID.
  10. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-click with value updateSale()
7. Search Sales
  1. In the Pages panel, click to open the Search Sales page.
  2. Click to select the Agent Select component.
  3. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-model with value data.agent
  4. Add another Angular Directive ng-options with value agent.AgentID as agent.AgentName for agent in agents
  5. Click to select the Destination Select component.
  6. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-model with value data.destination
  7. Add another Angular Directive ng-options with value destination.DestinationID as destination.DestinationName for destination in destinations
  8. Click to select the Amounts Above Input component.
  9. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-model with value data.above
  10. Click to select the Amounts Below Input component.
  11. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-model with value data.below
  12. Click to select the Button component.
  13. You will notice that the button is linked to Search Results - /page8. Since there are Route Input parameters declared for the Search Results page,
    you will notice under the link page is are text boxes to specify values for the agent, destination, above and below which must be passed into the Search Results page.
    For agent enter {{ data.agent }} For destination enter {{ data.destination }} For above enter {{ data.above }} For below enter {{ data.below }}
  14. Under Angular Directives at the bottom of the Properties panel, add Angular Directive ng-click with value searchSales()

Adding Page Controller JavaScript

8. Add Page Controller JavaScript:
Click the Code tab in the lower left corner of the screen. Click the Pages arrow to access each of the page controllers.
  1. Agent Bookings
    Replace line: function ($scope, $stateParams) {
    with 6 lines of code:
    function ($scope, $stateParams, GetAgentBookings) {
      GetAgentBookings.getPost()
      .then(function(response) {
        $scope.post = response;
        $scope.bookings =  $scope.post.records;
      });
  2. Sales
    Replace line: function ($scope, $stateParams) {
    with 6 lines of code:
    function ($scope, $stateParams, GetSales) {
      GetSales.getPost()
      .then(function(response) {
        $scope.post = response;
        $scope.sales =  $scope.post.records;
      });
  3. Add Agent
    Replace line: function ($scope, $stateParams) {
    with 25 lines of code:
    function ($scope, $stateParams, GetOffices, AddAgent) {
    
      $scope.offices = [];    
    
      $scope.data = {};
    
      $scope.addAgent = function(){
        var agent = $scope.data.agent;
        var office = $scope.data.office;
        $scope.hideButton=true;
    
        AddAgent.getPost(agent, office) 
        .then(function(response) {
          $scope.post = response;
         });
      };
    
      GetOffices.getPost()
      .then(function(response) {
        $scope.post = response;
        $scope.offices =  $scope.post.records;
    	$scope.offices.unshift({ "OfficeID": 0, "OfficeLocation": "--- Select Office Location ---" });
    	$scope.data.office=0;
      });
      
  4. Add Sale
    Replace line: function ($scope, $stateParams) {
    with 40 lines of code:
    function ($scope, $stateParams, GetAgents, GetDestinations, AddSale) {
    
      $scope.destinations = [];    
      $scope.agents = [];    
    
      $scope.data = {};
    
      $scope.addSale = function(){
        var agent = $scope.data.agent;
        var destination = $scope.data.destination;
        var s = $scope.data.saleDate;
        var m = s.getMonth()+1;
        var d = s.getDate();
        m = '0'+m; m = m.substr(-2,2);
        d = '0'+d; d = d.substr(-2,2);
        var saleDate = s.getFullYear()+'-'+m+'-'+d;
        var amount = $scope.data.amount;
        $scope.hideButton=true;
    
        AddSale.getPost(agent, saleDate, amount, destination) 
        .then(function(response) {
          $scope.post = response;
         });
      };
    
      GetAgents.getPost()
      .then(function(response) {
        $scope.post = response;
        $scope.agents =  $scope.post.records;
    	$scope.agents.unshift({ "AgentID": 0, "AgentName": "--- Select Agent ---" });
    	$scope.data.agent=0;
      });
    
      GetDestinations.getPost()
      .then(function(response) {
        $scope.post = response;
        $scope.destinations =  $scope.post.records;
    	$scope.destinations.unshift({ "DestinationID": 0, "DestinationName": "--- Select Destination ---" });
    	$scope.data.destination=0;
      });
  5. Search Sales
    Replace line: function ($scope, $stateParams) {
    with 22 lines of code:
    function ($scope, $stateParams, GetAgents, GetDestinations) {
    
      $scope.destinations = [];    
      $scope.agents = [];    
    
      $scope.data = {};
    
      GetAgents.getPost()
      .then(function(response) {
        $scope.post = response;
        $scope.agents =  $scope.post.records;
    	$scope.agents.unshift({ "AgentID": 0, "AgentName": "--- Select Agent ---" });
    	$scope.data.agent=0;
      });
    
      GetDestinations.getPost()
      .then(function(response) {
        $scope.post = response;
        $scope.destinations =  $scope.post.records;
    	$scope.destinations.unshift({ "DestinationID": 0, "DestinationName": "--- Select Destination ---" });
    	$scope.data.destination=0;
      });
  6. Search Results
    Replace line: function ($scope, $stateParams) {
    with 22 lines of code:
    function ($scope, $stateParams, SearchSales) {
    
      $scope.data = { 
    	  "agent": $stateParams.agent,
    	  "destination": $stateParams.destination,
    	  "above": $stateParams.above,
    	  "below": $stateParams.below
      };
    
      var criteria = '';
      if($scope.data.agent > 0) criteria += ", AgentID = "+$scope.data.agent;
      if($scope.data.destination > 0) criteria += ", DestinationID = "+$scope.data.destination;
      if($scope.data.above > 0) criteria += ", Amounts Above $"+$scope.data.above;
      if($scope.data.below > 0) criteria += ", Amounts Below $"+$scope.data.below;
    
      $scope.data.criteria = criteria.substr(2);
    
      SearchSales.getPost($scope.data.agent, $scope.data.destination, $scope.data.above, $scope.data.below)
      .then(function(response) {
        $scope.post = response;
        $scope.sales =  $scope.post.records;
      });
  7. Update Sale
    Replace line: function ($scope, $stateParams) {
    with 84 lines of code:
    function ($scope, $stateParams, GetAgents, GetDestinations, GetSale, DeleteSale, UpdateSale) {
    
      $scope.destinations = [];    
      $scope.agents = [];
      $scope.sale = {};
    
      $scope.data = { "saleId": $stateParams.saleId };
    
      GetAgents.getPost()
      .then(function(response) {
        $scope.post = response;
        $scope.agents =  $scope.post.records;
      });
    
      GetDestinations.getPost()
      .then(function(response) {
        $scope.post = response;
        $scope.destinations =  $scope.post.records;
      });
    
      var saleId;
      var original_AgentKey;
      var original_SaleDate;
      var original_Amount;
      var original_DestinationKey;
    
    
      GetSale.getPost($scope.data.saleId)
      .then(function(response) {
        $scope.post = response;
        $scope.sale =  $scope.post.records[0];
    	SetVariables();
      });
    
      SetVariables = function(){
        $scope.data.agentName=$scope.sale.AgentName;
        $scope.data.agentKey=$scope.sale.AgentKey;
        $scope.data.destinationKey=$scope.sale.DestinationKey;
        $scope.data.destinationName=$scope.sale.DestinationName;
    
        $scope.data.saleDate=new Date(parseInt($scope.sale.SaleTime));
    
        $scope.data.amount=parseFloat($scope.sale.Amount);
        saleId = $scope.sale.SaleID;
        original_AgentKey = $scope.sale.AgentKey;
        original_SaleDate = $scope.sale.SaleDate;
        original_Amount = $scope.sale.Amount;
        original_DestinationKey = $scope.sale.DestinationKey;
      };
    
      $scope.agentChanged = function(){
    	alert("AgentID was changed to "+$scope.data.agent);
      }
    
      $scope.deleteSale = function(){
        if(confirm("Are you sure you want to delete this sale?"))
        {
          $scope.hideDeleteButton=true;
    	  $scope.hideUpdateForm=true;
    
          DeleteSale.getPost(saleId, original_AgentKey, original_SaleDate, original_Amount, original_DestinationKey) 
          .then(function(response) {
            $scope.post = response;
           });
    	}
      };
    
      $scope.updateSale = function(){
    
        var s = $scope.data.saleDate;
        var m = s.getMonth()+1;
        var d = s.getDate();
        m = '0'+m; m = m.substr(-2,2);
        d = '0'+d; d = d.substr(-2,2);
        var saleDate = s.getFullYear()+'-'+m+'-'+d;
    
        UpdateSale.getPost(saleId, original_AgentKey, original_SaleDate, original_Amount, original_DestinationKey, 
          $scope.data.agentKey, saleDate, $scope.data.amount, $scope.data.destinationKey) 
        .then(function(response) {
          $scope.post = response;
          $scope.sale =  $scope.post.SaleRecord;
    	  SetVariables();
         });
      };

Adding API Services JavaScript

9. In the left Code panel, scroll down to Other JS. Click to open the services.js code.

The first line of services.js should be: angular.module('app.services', [])

Just after the first line, insert the following 212 lines of code:
.service('GetAgentBookings', function($http) {
  return {
    getPost: function() {
      var columns="AgentName, OfficeLocation, SUM(1) AS NumSales, SUM(IF(Amount IS NOT NULL,Amount,0)) AS Total";
      var table=encodeURIComponent("AGENT LEFT JOIN SALE ON AgentKey=AgentID LEFT JOIN OFFICE ON OfficeKey=OfficeID");
      var group="AgentID";
      var order="Total DESC";
      var query = '?columns='+columns;
      query += '&table='+table;
      query += '&group='+group;
      query += '&order='+order;

      return $http.get('https://secrdir.com/campus/ionic/list.php'+query)
      .then(function (response) {
        return response.data;
      });
    }
  };
})

.service('GetSales', function($http) {
  return {
    getPost: function() {
      var columns = "SaleID, SaleDate, UNIX_TIMESTAMP(SaleDate)*1000 AS SaleTime, AgentKey, Amount, DestinationKey";
	  columns += ", AgentName, OfficeKey, OfficeLocation, DestinationName";
	  var tab = "SALE INNER JOIN AGENT ON AgentKey=AgentID INNER JOIN OFFICE ON OfficeKey=OfficeID ";
	  tab += " INNER JOIN DESTINATION ON DestinationKey=DestinationID";
      var table = encodeURIComponent(tab);
      var order="SaleID DESC";

      var query = '?columns='+columns;
      query += '&table='+table;
      query += '&order='+order;

      return $http.get('https://secrdir.com/campus/ionic/list.php'+query)
      .then(function (response) {
        return response.data;
      });
    }
  };
})

.service('GetOffices', function($http) {
  return {
    getPost: function() {

      var query = '?table=OFFICE&order=OfficeLocation';

      return $http.get('https://secrdir.com/campus/ionic/list.php'+query)
      .then(function (response) {
        return response.data;
      });
    }
  };
})

.service('GetAgents', function($http) {
  return {
    getPost: function() {

      var query = '?table=AGENT&order=AgentName';

      return $http.get('https://secrdir.com/campus/ionic/list.php'+query)
      .then(function (response) {
        return response.data;
      });
    }
  };
})

.service('GetDestinations', function($http) {
  return {
    getPost: function() {

      var query = '?table=DESTINATION&order=DestinationName';

      return $http.get('https://secrdir.com/campus/ionic/list.php'+query)
      .then(function (response) {
        return response.data;
      });
    }
  };
})

.service('AddAgent', function($http) {
  return {
    getPost: function(agent,office) {
      var query = '?AgentName='+agent;
      query += '&OfficeKey='+office;
      return $http.get('https://secrdir.com/campus/ionic/add_agent.php'+query)
      .then(function (response) {
        return response.data;
      });
    }
  };
})

.service('AddSale', function($http) {
  return {
    getPost: function(agent,saleDate,amount,destination) {
      var query = '?AgentKey='+agent;
      query += '&DestinationKey='+destination;
      query += '&Amount='+amount;
      query += '&SaleDate='+saleDate;
      return $http.get('https://secrdir.com/campus/ionic/add_sale.php'+query)
      .then(function (response) {
        return response.data;
      });
    }
  };
})

.service('SearchSales', function($http) {
  return {
    getPost: function(agent, destination, amountsAbove, amountsBelow) {
      var columns = "SaleID, SaleDate, UNIX_TIMESTAMP(SaleDate)*1000 AS SaleTime, AgentKey, Amount, DestinationKey";
	  columns += ", AgentName, OfficeKey, OfficeLocation, DestinationName";
	  var tab = "SALE INNER JOIN AGENT ON AgentKey=AgentID INNER JOIN OFFICE ON OfficeKey=OfficeID ";
	  tab += " INNER JOIN DESTINATION ON DestinationKey=DestinationID";
      var table = encodeURIComponent(tab);
      var order="SaleID DESC";
      var query = '?columns='+columns;
      query += '&table='+table;
      query += '&order='+order;

	  var where = "";
	  if(agent > 0 ) { where += " AND AgentKey="+agent ; }
	  if(destination > 0 ) { where += " AND DestinationKey="+destination ; }
	  if(amountsAbove > 0 ) { where += " AND Amount>='"+amountsAbove+"'" ; }
	  if(amountsBelow > 0 ) { where += " AND Amount<='"+amountsBelow+"'" ; }
	  if(where>'') {
		  where = where.substr(4) ;
		  where=encodeURIComponent(where);
		  query += '&where='+where ;
      }
      return $http.get('https://secrdir.com/campus/ionic/list.php'+query)
      .then(function (response) {
        return response.data;
      });
    }
  };
})

.service('GetSale', function($http) {
  return {
    getPost: function(saleId) {
      var columns = "SaleID, SaleDate, UNIX_TIMESTAMP(SaleDate)*1000 AS SaleTime, AgentKey, Amount, DestinationKey";
	  columns += ", AgentName, OfficeKey, OfficeLocation, DestinationName";
	  var tab = "SALE INNER JOIN AGENT ON AgentKey=AgentID INNER JOIN OFFICE ON OfficeKey=OfficeID ";
	  tab += " INNER JOIN DESTINATION ON DestinationKey=DestinationID";
      var table = encodeURIComponent(tab);

      var query = '?columns='+columns;
      query += '&table='+table;
      query += '&where='+encodeURIComponent("SaleID=" + saleId);

      return $http.get('https://secrdir.com/campus/ionic/list.php'+query)
      .then(function (response) {
        return response.data;
      });
    }
  };
})


.service('DeleteSale', function($http) {
  return {
    getPost: function(saleId, originalAgent, originalSaleDate, originalAmount, originalDestination) {
      var query = '?SaleID='+saleId;
      query += '&Original_AgentKey='+originalAgent;
      query += '&Original_DestinationKey='+originalDestination;
      query += '&Original_Amount='+originalAmount;
      query += '&Original_SaleDate='+originalSaleDate;

	  return $http.get('https://secrdir.com/campus/ionic/delete_sale.php'+query)
      .then(function (response) {
        return response.data;
      });
    }
  };
})


.service('UpdateSale', function($http) {
  return {
    getPost: function(saleId, originalAgent, originalSaleDate, originalAmount, originalDestination, 
		agent, saleDate, amount, destination) {
      var query = '?SaleID='+saleId;
      query += '&Original_AgentKey='+originalAgent;
      query += '&Original_DestinationKey='+originalDestination;
      query += '&Original_Amount='+originalAmount;
      query += '&Original_SaleDate='+originalSaleDate;
	  var changes = 0;
      if(agent != originalAgent) { query += '&AgentKey='+agent; changes += 1; }
      if(destination != originalDestination) { query += '&DestinationKey='+destination; changes += 1; }
      if(amount != originalAmount) { query += '&Amount='+amount; changes += 1; }
      if(saleDate != originalSaleDate) { query += '&SaleDate='+saleDate; changes += 1; }
	  if( changes == 0 )
      {
        var message = { "message" : "Nothing to update" };
        return message;
      }
      else
      {
		  return $http.get('https://secrdir.com/campus/ionic/update_sale.php'+query)
		  .then(function (response) {
			return response.data;
		  });
	  }
    }
  };
})
10. Save your work. In the upper left Pages panel, click to select the Home page. Then click the Preview icon at the top to test your app.
11. Once you know your app works, you can change every occurrence of https://secrdir.com/campus/ionic/ in services.js to the domain name and path to your APIs.

Exporting Your Mobile App from Ionic Creator to your Website

12. To export your app to your server,
  1. Click on the Cloud icon with the down arrow to export your application to your computer as a ZIP file.
  2. Open your cPanel on your web server.
  3. In the cPanel File Manager, create a new folder in the public_html directory named ct (for Campus Travel).
  4. Open the ct folder. Upload the zipped folder of your app into the ct folder on your server.
  5. Select the zipped file, right click and unzip the file.
  6. Test your app by going to the /ct/ directory of your website on your browser or mobile device.
  7. If your site is blank, the access permissions of the lib folder might not have been initialized correctly. To make sure,
    1. In your /ct/ directory, create a new file named chmod.php
    2. Enter the following line: <?php shell_exec('chmod -R 755 lib'); ?>
    3. Save the file. Execute by going to /ct/chmod.php
  8. Use the Developer's Web Console of your browser to track down errors you may have.


Richard Halverson, Jr., Ph.D. • University of Hawaii