I've having a problem to get the resolve mechanism working in my application.
I separated the webservice call into an extra module and using deferred/promise to have callbacks.
Before showing the state "workflowdefinitions.detail", the app should load the workflow definition be using the workflowDefinitionId of the $stateParams and call the function "getWorkflowDefinition" of the workflowDefinitionService at the service module.
I tried out multiple things that I had read here, but can't get it working. How do I need to handle the returned promise to pass the return data to the workflowDefinition defined by resolve?
Can this work with my services or do I have to define the service in a different way?
app.js
var atpApp = angular.module('atpApp', [ 'ui.router', 'workflowServices', 'workflowControllers' ]);
atpApp.config([ '$stateProvider', '$urlRouterProvider', '$locationProvider', function($stateProvider, $urlRouterProvider , $locationProvider) {
$urlRouterProvider.otherwise('/workflowdefinitions');
$stateProvider.state('workflowdefinitions', {
url : '/workflowdefinitions',
controller : 'WorkflowDefinitionListCtrl',
templateUrl : 'partials/workflowdefinition-list.html'
})
.state('workflowdefinitions.detail', {
url : '/:workflowDefinitionId',
views : {
'#' : {
templateUrl : 'partials/workflowdefinition-detail.html',
controller : 'WorkflowDefinitionDetailCtrl',
resolve: {
workflowDefinition: function($stateParams, workflowDefinitionService) {
return workflowDefinitionService.getWorkflowDefinition($stateParams.workflowDefinitionId);
}
}
}
}
});
} ]);
atpApp.run([ '$rootScope', '$state', '$stateParams', function($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
} ]);
Module for Services (workflowSevices.js)
var workflowServices = angular.module('workflowServices', []);
workflowServices.service('workflowDefinitionService', function($http, $q) {
var config = {headers: {
'Accept': 'application/json'
}
};
this.getWorkflowDefinitions = function(){
var deferred = $q.defer();
$http.get('http://localhost:8080/vms-atp-webapp/services/rest/workflows', config).
success(function(data, status) {
deferred.resolve(data);
}).error(function(data, status) {
deferred.reject(data);
});
return deferred.promise;
};
this.getWorkflowDefinition = function(workflowDefinitionId){
var deferred = $q.defer();
$http.get('http://localhost:8080/vms-atp-webapp/services/rest/workflows/'+workflowDefinitionId, config).
success(function(data, status) {
deferred.resolve(data);
}).error(function(data, status) {
deferred.reject(data);
});
return deferred.promise;
};
this.activateWorkflowDefinition = function(workflowDefinitionId){
var deferred = $q.defer();
$http.post('http://localhost:8080/vms-atp-webapp/services/rest/workflows/'+workflowDefinitionId+"/activate", config).
success(function(data, status) {
deferred.resolve(data);
}).error(function(data, status) {
deferred.reject(data);
});
return deferred.promise;
};
this.deactivateWorkflowDefinition = function(workflowDefinitionId){
var deferred = $q.defer();
$http.post('http://localhost:8080/vms-atp-webapp/services/rest/workflows/'+workflowDefinitionId+"/suspend", config).
success(function(data, status) {
deferred.resolve(data);
}).error(function(data, status) {
deferred.reject(data);
});
return deferred.promise;
};
});
This concept should be working. There is a plunker, which should be doing almost the same you've tried above. No changes, as is. (as is in the code above)
The only change - for example purposes - is the service method getWorkflowDefinition, which does delay because of $timeout service, but then returns the param passed
this.getWorkflowDefinition = function(param){
var deferred = $q.defer();
$timeout(function(){
deferred.resolve(param);
}, 750)
return deferred.promise;
};
So, your concept, design is working, check more here: plunker
Additionally you don't need the boiler plate for deferred/resolve everywhere.
This code
var deferred = $q.defer();
$http.post( 'http://localhost:8080/vms-atp-webapp/services/rest/workflows/' + workflowDefinitionId +"/suspend", config).
success(function(data, status) {
deferred.resolve(data);
}).error(function(data, status) {
deferred.reject(data);
});
return deferred.promise;
can be simplified to
simple
return $http.get('http://localhost:8080/vms-atp-webapp/services/rest/workflows', config);
This is because the $http.get returns a promise which when fulfilled is internally resolved/rejected on success and error.
Related
I am using angularjs and cordova tool for creating application.
I have created service, which contains code for calling APIs. and in that I want to return response to my angular controller.
My code is,
Service,
JodoModule.factory('commonServices', function ($http, $q, $rootScope) {
return {
getServiceData: function (url) {
$rootScope.loading = true;
var deferred = $q.defer();
var req = {
method: 'GET',
url: url
}
$http(req).success(function (data) {
alert("data in service = " + JSON.stringify(data.Data));
deferred.resolve(data);
}).error(function (data, status, headers, config) {
deferred.reject(status);
});
return deferred.promise;
}
};
});
My controller is,
commonServices.getServiceData("My url").
success(function (data, status, headers, config) {
alert(data);
}).
error(function (data, status, headers, config) {
alert("Got error");
});
In above code, in service, its showing elert message for JSON.stringify(data.Data)); in success block, so data is comming, but its not executing deferred.resolve(data); properly...
in Web tool bar its giving me error,
ie. TypeError: undefined is not a function
My o/p is :
{"status":"SUCCESS","Message":"success","Token":"","Data":[{"Id":17,"UserId":"477f1919-6b80-4804-a325-ac0cb05bcd3e","UserName":"honey","FirstName":"honey","LastName":null,"ProfilePic":false,"Status":2}]}
How can I solve this error. ?
Ordinary $q promises don't have a .success() or .error() method, but you shouldn't be using the deferred antipattern anyway. Instead, do this:
JodoModule.factory('commonServices', function ($http, $rootScope) {
return {
getServiceData: function (url) {
$rootScope.loading = true;
var req = {
method: 'GET',
url: url
};
return $http(req).then(function (result) {
alert("data in service = " + JSON.stringify(result.data.Data));
return result.data;
});
}
};
});
Controller:
commonServices.getServiceData("My url").
then(function (data) {
alert(data);
}).
catch(function (result) {
alert("Got error");
});
Quite a bit cleaner, ay?
I'm trying to write an Angular service and it seems like there is something missing. My problem is its not returning any value to my Angular controller
getPrepTimes() method is not returning the http data
But when I check the network (via Chrome dev tools) it will correctly call the external api and return a json object as a response
#my service
'use strict';
angular.module('recipeapp')
.service('prepTimeService',['$http', function($http){
this.prepTime = getPrepTimes();
function getPrepTimes(){
$http({
url: '/prep_times/index.json',
method: 'GET'
})
.success(function (data, status, header, config){
return data;
});
};
}
]);
#controller
'use strict';
angular.module('recipeapp')
.controller('recipeCtrl', ['$scope', 'prepTimeService', function($scope, prepTimeService){
$scope.prep_time = prepTimeService.prepTime;
}]);
When I checked the method getPrepTimes() with returning a string it works. What could be missing here?
A couple things are wrong with the above. You assign this.prepTime to getPrepTimes(). The () there will invoke getPrepTimes immediately, and not when you actually call it! You also need to utilize callbacks to get your data back and use it:
angular.module('recipeapp').service('prepTimeService',['$http', function($http){
this.prepTime = getPrepTimes;
function getPrepTimes(callback) {
$http({
url: '/prep_times/index.json',
method: 'GET'
}).success(function (data, status, header, config){
callback(data);
});
};
}]);
And now use it like so:
prepTimeService.prepTime(function(data) {
$scope.prep_time = data;
});
Calls to the $http service are async, which means you need to return a promise (and not a value):
this.prepTime = function() {
return $http({
url: '/prep_times/index.json',
method: 'GET'
});
};
And on the controller:
angular.module('recipeapp')
.controller('recipeCtrl', ['$scope', 'prepTimeService', function($scope, prepTimeService){
$scope.prep_time = prepTimeService.prepTime()
.success(function (data, status, header, config){
$scope.someVar = data;
});
}]);
Wrap answer with promise:
var self = this;
var deferred = $q.defer();
self.getPrepTimes = function() {
$http({
url: '/prep_times/index.json',
method: 'GET'
})
.success(function(data, status, headers, config) {
if (data.error === undefined) {
deferred.resolve(data);
} else {
if (data.error !== undefined) {
} else {
deferred.reject(data);
}
}
}).error(function(data, status, headers, config) {
deferred.reject(data);
});
return deferred.promise;
};
In controller call it:
prepTimeService.getPrepTimes().then(function(result) {
$scope.prep_time = result;
},
function(error) {
// show alert
});
Im a complete angularjs newbie. So hopefully I am somewhat on track.
I have a datacontext configured like
(function () {
'use strict';
var serviceId = 'datacontext';
angular.module('app').factory(serviceId, ['common', '$http', datacontext]);
function datacontext(common, $http) {
var $q = common.$q;
var service = {
getCustomerGroups: getCustomerGroups
};
return service;
function getCustomerGroups() {
var groups = [];
$http({ method: 'GET', url: '/api/getgroups' }).
success(function (data, status, headers, config) {
console.log(status);
console.log(headers);
console.log(data);
groups = data;
return $q.when(groups);
}).
error(function (data, status, headers, config) {
console.log(data);
// called asynchronously if an error occurs
// or server returns response with an error status.
});
return $q.when(groups);
}
}
})();
Within my view I am using ngTagsInput
<tags-input ng-model="groups"
display-property="GroupName"
placeholder="Add Customer Group"
enableeditinglasttag="false"
class="ui-tags-input"
replace-spaces-with-dashes="false">
</tags-input>
And finally my controller
(function () {
'use strict';
var controllerId = 'customers';
angular.module('app').controller(controllerId, ['common','$scope','$http','datacontext', customers]);
function customers(common,$scope,$http,datacontext) {
var vm = this;
vm.title = 'Customers';
$scope.groups = [];
function getGroups() {
return datacontext.getCustomerGroups().then(function (data) {
return $scope.groups = data;
});
}
activate();
function activate() {
var promises = [getGroups()];
common.activateController(promises, controllerId)
.then(function() {
}
);
}
}
})();
I am not getting any errors and I can see the correct data is returned in the success method of $http. However the tag is not populated. Is it because the tag is calling the datasource before the $http has completed?
I am not sure how $q.when works, but it returns promise but does not resolve it. You should us the defer api.
So at start set
var defer = common.$q.defer();
and later in success do defer.resolve.
success(function (data, status, headers, config) {
console.log(status);
console.log(headers);
console.log(data);
groups = data;
defer.resolve(data);
and see if it works.
I am trying to retrieve the "cart" in the following way Factory->Service->Controller.
I am making an $http call but it is returning an object. If I debug I can see that the request is made and is retrieving the data (in the network section of the debugger).
angular.module('companyServices', [])
.factory('CompanyFactory', ['$http', function($http){
return {
getCart: function(cartId) {
var promise = $http.get('company/Compare.json', {params: {'wsid': cartId}})
success(function(data, status, headers, config) {
return data;
}).
error(function(data, status, headers, config) {
return "error: " + status;
});
}
};
}]);
angular.module('itemsServices', [])
.service('ItemsServices', ['CompanyFactory', function(CompanyFactory){
var cartId = new Object();
this.getCartId = function(){
return cartId;
};
this.cartId = function(value){
cartId = value;
};
this.getCart = function(){
return CompanyFactory.getCart(this.getCartId()).then(function(data){return data});
};
};
.controller('CompareItemsCtrl', ['$scope', '$location', 'ItemsServices', function($scope, $location, ItemsServices){
var params = $location.search().wsid;
ItemsServices.cartId(params);
console.log('ItemsServices.getCart()');
console.log(ItemsServices.getCart());
};
Thank you
Since $http returns a promise, I think you would be better of passing in your success and error functions to getCart()
.controller('CompareItemsCtrl', ['$scope', '$location', 'ItemsServices', function($scope, $location, ItemsServices){
var params = $location.search().wsid;
ItemsServices.cartId(params);
console.log('ItemsServices.getCart()');
console.log(ItemsServices.getCart());
ItemsService.getCart().then(function(response){
console.log('success');
},function(response){
console.log('error');
});
};
I'm pretty new to with AngularJS. When I'm calling $http.get I get a $http is not defined error.
This is the content of my Module:
var demoApp = angular.module('demoApp', []);
demoApp.config(function ($routeProvider) {
$routeProvider.
when('/view1',
{
controller: 'SimpleController',
templateUrl: 'View1.html'
}).
when('/view2',
{
controller: 'SimpleController',
templateUrl: 'View2.html'
})
.otherwise({ redirectTo: '/view1' });
});
demoApp.factory('simpleFactory', function () {
var factory = {};
factory.getAnnounces = function ($http) {
$http.post("http://localhost:57034/Announce/GetAllAnnounces")
.success(function (data, status, headers, config) {
return data;
}).error(function (data, status, headers, config) {
return status;
});
};
return factory;
});
demoApp.controller('SimpleController', function ($scope,simpleFactory) {
$scope.announces = [];
init();
function init()
{
$scope.announces= simpleFactory.getAnnounces();
}
});
What am I missing here? Cheers.
You need to review your code as follows:
demoApp.factory('simpleFactory', ['$http', function ($http) {
return {
getAnnounces: function () {
$http.post("http://localhost:57034/Announce/GetAllAnnounces")
.success(function (data, status, headers, config) {
return data;
}).error(function (data, status, headers, config) {
return status;
});
}
};
}]);
There's no need to pass the $http variable in the getAnnounces method definition, because it is defined already in the scope of the factory function.
I am using parameter aliasing for AngularJS in order to avoid issues with minifiers, see 'A note on minification' on the AngularJS web site.
Note anyway that $http.post.success and $http.post.error are asynchronous and you won't be able to get the data unless you're using promises ($q), see here. Therefore you could change the code this way:
demoApp.factory('simpleFactory', ['$http', '$q', function ($http, $q) {
return {
getAnnounces: function () {
var deferred = $q.defer();
$http.post("http://localhost:57034/Announce/GetAllAnnounces")
.success(function (data, status, headers, config) {
deferred.resolve(data);
}).error(function (data, status, headers, config) {
deferred.reject(data);
});
return deferred.promise;
}
};
}]);
And in the SimpleController:
demoApp.controller('SimpleController', ['simpleFactory', '$scope', function (simpleFactory, $scope) {
$scope.announces = [];
simpleFactory.getAnnounces()
.then(function(data) {
// call was successful
$scope.announces = data;
}, function(data) {
// call returned an error
$scope.announces = data;
});
}]);