With the development of the landing page, we are ready to add the trip details page. This page will be used to edit the trip information, manage sponsors, activities, and waivers. Due to the amount of data displayed on the page, I think that the participants listing will get their own page.
We've already, in the last post, added the trip route to the router. But just as a refresher, it looks like the following:
So now it's time to begin building out the trip.html template. The editing paradigm that I've been messing around with of late is simply get the JSON object from the CF, edit the object via the model directly on the template, and then pass the object back to CF. Rinse and repeat.
We are going to pass the trip object to the
So I have changed this:
Now technically, we could abstract
Ok, rant over - back to the code. Just one final contrast for this post concerning the
Both make sense and are easy to understand. However, the latter one is going to save quite a bit of development time.
Hmmm...I hadn't expected this post to be as long as it is. So a Part 2 will be forthcoming and focus on the data coming into Coldfusion and saving it back to the database.
Cheers!
We've already, in the last post, added the trip route to the router. But just as a refresher, it looks like the following:
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"})
});
The next steps are to create the trip template and controller files. Because a parameter is being passed to the trip controller, the $stateParams
need to be injected. What does that mean? Well, it's a complicated but short way of saying that we have to let the controller know what it can use. And we do this by adding to the object array and function parameters just we did with the dataService
.
angular.module('core').controller('TripController',['$scope','dataService','$stateParams', function($scope,dataService,$stateParams){
$scope.trip = {};
dataService.call('getTrip&_id=' + $stateParams.id).then(function(data){
$scope.trip = data.data;
})
}]);
The $stateParams
stores the parameters passed into the route. In this case, we need the id
of the trip being selected by the user. The id will be passed to the getTrip
function via the dataService
. The next step is to create the CF function. <cffunction name="getTrip" returnformat="json" returntype="struct" access="remote">
<cfargument name="_id" required="yes" type="string">
<cfset _trip = structNew()>
<cfquery name="_qTrip" datasource="#_ds#">
select trip_name,
author_pidm,
destination,
trip_type,
purpose,
comments
from trips t
where t.trip_id = <cfqueryparam value="#_id#" cfsqltype="cf_sql_integer">
</cfquery>
<cfloop query="_qTrip">
<cfset _trip.name = trip_name>
<cfset _trip.authorID = author_pidm>
<cfset _trip.destination = destination>
<cfset _trip.type = trip_type>
<cfset _trip.comments = comments>
<cfset _trip.purpose = purpose>
</cfloop>
<cfreturn _trip>
</cffunction>
This is the beginning of the trip function as there will be a lot more data elements to gather. But in my development pattern, I like to test things out before writing too much code. In this round of testing and after a bunch of "why isn't this working?!?!" I discovered I had forgotten to add the trip.js
controller to the main.cfm
page.So now it's time to begin building out the trip.html template. The editing paradigm that I've been messing around with of late is simply get the JSON object from the CF, edit the object via the model directly on the template, and then pass the object back to CF. Rinse and repeat.
<div ng-controller="TripController as ctrlTrip">
<h2>{{trip.NAME}}<br><small>{{trip.DESTINATION}}</h2>
<div class="input-group" style="padding-bottom:10px">
<span class="input-group-addon" style="width:125px">Name</span>
<input class="form-control" ng-model="trip.NAME" style="width:400px">
</div>
<div class="input-group" style="padding-bottom:10px">
<span class="input-group-addon" style="width:125px">Destination</span>
<textarea class="form-control" ng-model="trip.DESTINATION" style="width:400px"></textarea>
</div>
<div class="input-group" style="padding-bottom:10px">
<span class="input-group-addon" style="width:125px">Comments</span>
<textarea class="form-control" ng-model="trip.COMMENTS" style="width:400px"></textarea>
</div>
<div class="input-group" style="padding-bottom:10px">
<span class="input-group-addon" style="width:125px">Trip Type</span>
<select class="form-control" style="width:300px" ng-model="trip.TYPE">
<option ng-repeat="tripType in tripTypes" value="{{tripType.CODE}}">{{tripType.NAME}}</option>
</select>
</div>
<button class="btn btn-primary" ng-click="saveTrip(trip)">Save Trip</button>
</div>
With a very basic template in place, which will be expanded to accommodate the other aspects of a trip, we can begin written the save code, both in the dataService and the CFC. Since there are going so many many values that need to be saved, it doesn't make sense to pass those values via the url string. Doing so would required breaking down the object into strings, etc.We are going to pass the trip object to the
dataService
, and then the dataService
is going to pass the object to Coldfusion. The first thing to do is create the dataService
method to accept the object. Until now, I have always made a new method for each object that needs processing to happen. However, as I was sitting here looking at the code, I realized I could abstract this just a little further and make it a bit more generic, like the this.call()
method.So I have changed this:
//params template
this.saveTrip = function(_trip){
var _params = {trip: JSON.stringify(_trip)}
return $http({
method: 'POST',
url: 'trips.cfc?method=saveTrip',
headers: {
'Content-Type': undefined
},
data: _params
}).then(function successCallback(response){
console.log(response.data);
return response;
},
function errorCallback(response){
console.log('ruh-roh')
}
);
}
to this:
this.process = function(_method, _data){
var _params = {objectData: JSON.stringify(_data)}
return $http({
method: 'POST',
url: 'trips.cfc?method=' + _method,
headers: {
'Content-Type': undefined
},
data: _params
}).then(function successCallback(response){
console.log(response.data);
return response;
},
function errorCallback(response){
console.log('ruh-roh')
}
);
}
Notice the subtle differences. Rather than doing a this.saveTrip
and passing the trip object, we are going to process something, this.process
, via some method, _method
. In both cases, the object gets stringified into the _params
variable. Next we are going to post to the trips.cfc
. For the this.saveTrip
we explicitly state the saveTrip
method as part of the url. But for the this.process
method, we put the _method
value into the url. With this simple level of abstraction, we are going to save a lot of time coding, debugging and maintaining.Now technically, we could abstract
this.process()
even further and allow arguments for the CFC and path. But to me this is over-abstraction - if that's a thing. I think it's important to maintain context toward the application when developing. Just like a database can be normalized to the point of being a bunch of tables with columns and columns of numbers, code can be abstracted to the point that it requires layers and layers of coding to get Hello World on the screen. Abstraction is a good thing because it yields us libraries like AngularJS. But too much of a good thing can be unproductive.Ok, rant over - back to the code. Just one final contrast for this post concerning the
dataService
call.dataService.saveTrip(_trip).then(function(data){});
dataService.process('saveTrip',_trip).then(function(data){});
Both make sense and are easy to understand. However, the latter one is going to save quite a bit of development time.
Hmmm...I hadn't expected this post to be as long as it is. So a Part 2 will be forthcoming and focus on the data coming into Coldfusion and saving it back to the database.
Cheers!
Comments
Post a Comment