Reputation: 169
I am trying to create code that uses services (factory) and ngResource to send a request to a RESTful service that performs and action and sends optional results back based on business logic.
I am aware of a question that talks about something similar found at Passing multiple parameters from controller to factory in angularjs . I'm having problems getting it to work for me and there also is a lack of explanation.
I'm writing this to understand how it works, best practice and so there's a repository that's good for newbies like myself in future. No disrespect to the author of the solution provided above but it probably assumes a level of cleverness I've not yet attained ;-)
Here goes:
My controller
swof.controller('scheduleController', ['$scope', '$log', '$http', '$filter','moment', 'scheduleServicePeriod', function($scope, $log, $http, $filter, moment, scheduleServicePeriod) {
$scope.name = 'scheduleController::set default values and provide function to generate new schedule';
$log.info('Controller: '+ $scope.name);
$scope.years = ["2017", "2018", "2019","2020","2021","2022"];
$scope.selectedYear = "2017";
$scope.selectedPeriod = Math.ceil(moment().format('w')) | 1 ;
$scope.genSchedule = function()
{
// when button is pressed function 'genSchedule' is called that either has default value for selectedYear and selectedPeriod or one user has selected. This bit works
scheduleServicePeriod.post({ s_year: $scope.selectedYear, s_period: $scope.selectedPeriod }).$promise.then(function(data){
$scope.schedulegen = data;
$scope.genScheduleResponse=moment().format('h:mm:ss a') + " " + data.message;
}, function(data) {
$log.error();('Error: ' + data);
})};
}]);
My factory service
swof.factory('scheduleServicePeriod', function($resource)
{
var data = $resource('/api/schedules/period/:s_year/:s_period',{s_year: "@s_year",s_period: "@s_period" },
{
'post':
{
method: 'POST',
params: {},
isArray:true
}
});
return data;
});
My RESTful Web Service
router.route('/schedules/period/:schedule_year/:schedule_period')
.post(function(req,res)
{
// create record
var query = getEngineerIDs();
var jsonMessage = "Success: Generated schedule for year = " + req.params.schedule_year + " and period starting week number = " + req.params.schedule_period ;
console.log(parseInt(req.params.schedule_period%2),parseInt(req.params.schedule_period));
query.exec(function(err,records)
{
if(err) return console.log(err);
var results = SwfFn.populateCalendar(SwfFn.assignEngineers(records),+
req.params.schedule_year,req.params.schedule_period);
if ( results.length == 0 ) {
jsonMessage = "Failed: Start year/week in past";
}
console.log(jsonMessage);
for (var count in results)
{
Schedule.findOneAndUpdate (
{ ymd: results[count].ymd, shift: results[count].shift },
results[count],
{upsert: true, new: true, runValidators: true},
function (err,res) { if (err) res.send(err); }
);
}
res.json({message: jsonMessage });
});
})
What happens
Appreciate the help!
Upvotes: 0
Views: 26
Reputation: 169
It actually worked! What I was doing wrong was printing out the wrong values when using console.log for debugging and the way I displayed the response message in the UI.
To summarise I want to make an API call along the lines of POST /api/schedules/period//
The call does a calculation and sends back a response I want to show the end-user on the screen.
Here's the working code which can still be improved but is a reasonably good example for basic use cases. The syntax for sending down the parameters is fairly straightforward if you follow the example to is logical conclusion.
Controller
swof.controller('scheduleController', ['$scope', '$log', '$http', '$filter','moment', 'scheduleServicePeriod', function($scope, $log, $http, $filter, moment, scheduleServicePeriod) {
$scope.name = 'scheduleController::set default values and provide function to generate new schedule';
$log.info('Controller: '+ $scope.name);
$scope.years = ["2017", "2018", "2019","2020","2021","2022"];
$scope.selectedYear = "2017";
$scope.selectedPeriod = Math.ceil(moment().format('w')) | 1 ;
$scope.genSchedule = function()
{
scheduleServicePeriod.post({ s_year: $scope.selectedYear, s_period: $scope.selectedPeriod }).$promise.then(function(data){
$scope.schedulegen = data;
$scope.genScheduleResponse=moment().format('h:mm:ss a') + " " + data.message;
}, function(data) {
$log.error();('Error: ' + data);
})};
}]);
Factory Service
swof.factory('scheduleServicePeriod', function($resource)
{
var data = $resource('/api/schedules/period/:s_year/:s_period',{s_year: "@s_year",s_period: "@s_period" },
{
'post':
{
method: 'POST'
}
});
return data;
});
RESTful call
router.route('/schedules/period/:schedule_year/:schedule_period')
.post(function(req,res)
{
// create record
var query = getEngineerIDs();
var jsonMessage = "Success: Generated schedule for year/period [" + req.params.schedule_year + "/" + req.params.schedule_period +"]" ;
query.exec(function(err,records)
{
if(err) return console.log(err);
var results = SwfFn.populateCalendar(SwfFn.assignEngineers(records),+
req.params.schedule_year,req.params.schedule_period);
if ( results.length == 0 ) {
jsonMessage = "Failed: Start year/week in past";
}
for (var count in results)
{
// Write record to Mongo using upsert; if records for future date already
// here then overwrite them otherwise insert. This is ok since the period
// is in the future
Schedule.findOneAndUpdate (
{ ymd: results[count].ymd, shift: results[count].shift },
results[count],
{upsert: true, new: true, runValidators: true},
function (err,res) { if (err) res.send(err); }
);
}
res.json({message: jsonMessage });
console.log(jsonMessage);
});
Web Page
<div>
<h3>Generate</h3>
<h4>Generate schedule for future periods</h4>
<p>Select year and week start period to generate a schedule for future support slots. Previously generated values will be lost. You cannot generate a scheule for periods in the past or the current period we are in.</p>
<form name="scheduleGenerate">
<select ng-model="selectedYear" ng-options="x for x in years"></select>
Start Week (1-51 [odd numbers]):
<input ng-model="selectedPeriod" type="number" name="genperiod" placeholder="1" min="1" max="51" step="2" onkeydown="return false">
<input type="button" class="click" id="click" value="Generate" ng-click="genSchedule()">
<label class="control-label"> {{ genScheduleResponse }}</label>
</form>
</div>
Hope someone finds this useful.
Upvotes: 0