I am working on an app to allow users to login with different level or access to an application. I added a resolve dependencies to get the list of users. It did return a list of correct users. How do I pass this object to the controller?
I follow a similar example on the website, but my getPrelogin object is always undefined. What did I do wrong?
.state('registration.login', {
url: '/Login',
resolve: {
preLoginFactory: 'preLoginFactory',
getPrelogin: function (preLoginFactory) {
var result = preLoginFactory();
result.then(function (result) {
return result.data.Model.IntroMessage;
})
}
},
views: {
"content#": {
templateUrl: '/Account/Login',
controller: function ($scope, $stateParams, $location, LoginFactory, getPrelogin, preLoginFactory) {
console.log('the value of get pre login')
console.log(getPrelogin);
$scope.introMessage = getPrelogin;
$scope.loginForm = {
emailAddress: '',
password: '',
rememberMe: false,
returnUrl: $stateParams.returnUrl,
loginFailure: false
};
$scope.login = function () {
var result = LoginFactory($scope.loginForm.emailAddress, $scope.loginForm.password, $scope.loginForm.rememberMe);
result.then(function (result) {
if (result.success) {
if ($location.loginForm.returnUrl !== 'undefined') {
$location.path('/routeOne');
} else {
$location.path($scope.loginForm.returnUrl);
}
} else {
$scope.loginForm.loginFailure = true;
}
});
};
}//"LoginController"
}
}
})
Your resolve object getPrelogin should return result variable, because promise preLoginFactory factory does return promise object. By injecting getPrelogin inside controller you would directly get data returned from getPrelogin which is result.data.Model.IntroMessage.
Code
resolve: {
preLoginFactory: 'preLoginFactory',
getPrelogin: function(preLoginFactory) {
var result = preLoginFactory();
return result.then(function(response) {
return response.data.Model.IntroMessage;
})
}
},
You must return your promise:
getPrelogin: function (preLoginFactory) {
var result = preLoginFactory();
return result.then(function (result) {
return result.data.Model.IntroMessage;
})
}
Related
I have the following resolve:
.state('posts', {
url: '/posts/{id}',
templateUrl: 'posts.html',
controller: 'postsController as postsCtrl',
resolve: {
post: getSinglePostWrapper
}
})
and helper function
getSinglePostWrapper.$inject = ['postsService', '$stateParams'];
function getSinglePostWrapper(postsService, $stateParams) {
return postsService.getSinglePost($stateParams.id);
}
and my controller looks like this:
angular.module('flapperNews')
.controller('postsController', postsController);
postsController.$inject = ['postsService', 'post'];
function postsController(postsService, post) {
var vm = this;
vm.post = post;
console.log(post); //undefined here
}
I'm getting an undefined "post" when I try to inject the post from the resolve. I tried logging the post in the getSinglePostWrapper function, and it logs the correct object. I seem to be losing some binding or something from the resolve to the controller.
posts service
angular.module('flapperNews')
.factory('postsService', postsService);
postsService.$inject = ['httpService'];
function postsService(httpService) {
return {
getSinglePost: getSinglePost
}
function getSinglePost(postId) {
httpService.baseGet('/posts/' + postId)
.then(function(data) {
return data;
}, function(data) {});
}
}
httpservice
angular.module('httpService', [])
.factory('httpService', httpService);
httpService.$inject = ['$http', '$q'];
function httpService($http, $q) {
return {
baseGet: baseGet
}
function baseGet(url) {
return $http.get(url).then(
function (result) {
return result.data;
},
function (result) {
return $q.reject(result);
}
);
}
}
and I've injected httpservice into the first place I declare the flapperNews module.
FYI- everything is working. Other http requests are fine. This one is fine too. It just doesn't inject the post into the controller.
Promise chain breaks here.
function getSinglePost(postId) {
httpService.baseGet('/posts/' + postId)
.then(function(data) {
return data;
}, function(data) {});
}
You don't return the promise, hence post will be resolved to undefined before httpService.baseGet request has been finished.
try this:
.state('posts', {
url: '/posts/{id}',
templateUrl: 'posts.html',
controller: 'postsController as postsCtrl',
resolve: {
post: function('postsService', '$stateParams') {
return postsService.getSinglePost($stateParams.id);
}
})
angular.module('flapperNews')
.controller('postsController', function($scope, post){
$scope.post = post;
console.log($scope.post); //undefined here
});
In a controller, I need to retrieve the status of a segment. The segments are loaded from an API using $resource.
In the resource, segmentsresource.js I have:
angular.module('appApp')
.factory('SegmentsResource', function ($resource) {
return $resource('http://localhost:3000/api/v1/segments/:id');
});
In the service, segmentsservice.js I have:
angular.module('appApp')
.service('SegmentsService', function (SegmentsResource) {
this.getSegmentStatus = function(segmentId) {
return SegmentsResource.get({
id: segmentId
}, function(segment) {
return segment.status;
})
};
});
I'm trying to do return segment.status so I can use the result ('available', 'translated', etc) in the controller, main.js:
$scope.checkAndEditSegment = function(segmentId) {
SegmentsService.getSegmentStatus(segmentId)
.then(function(status) {
if (status === 'available') {
console.log('segment is available');
}
});
};
However, this doesn't work. Console spits: TypeError: Cannot read property 'then' of undefined', so I have a problem with promises.
How to fix this?
But why you are taking this long route when you can simply call the factory from controller.
angular.module('appApp')
.factory('SegmentsResource', function ($resource) {
return $resource('http://localhost:3000/api/v1/segments/:id');
});
$scope.checkAndEditSegment = function(segmentId) {
SegmentsResource.get(segmentId)
.then(function(status) {
if (status === 'available') {
console.log('segment is available');
}
});
};
I resolved using $q:
In the service:
this.getSegmentStatus = function(segmentId) {
var dfd = $q.defer();
SegmentsResource.get({ id: segmentId }, function(segment) {
dfd.resolve(segment.status);
})
return dfd.promise;
};
In the controller:
SegmentsService.getSegmentStatus(segmentId)
.then(function(status) {
console.log(status);
});
I've this service, it returns a list of students asynchronously using callback:
studentModule.factory('StudentService', function (DB_URL) {
return {
getAllStudents: function (callback) {
var Datastore = require('nedb'),
path = require('path');
db = {};
db.students = new Datastore({
filename: DB_URL + '/students.db',
autoload: true
});
db.students.find({}, function (err, stds) {
callback(stds);
});
}; //end return
My old way to use it in controller:
StudentService.getAllStudents(function(sts) {
$scope.students = sts;
$scope.$apply();//notify angular about the change
});
This works for me, but now i want to use some best practices. I need to resolve the result in the route before coming to the controller, here what i did:
.state('payment', {
url: '/payment',
templateUrl: 'frontend/components/payment/views/payment.html',
controller: 'PaymentController',
resolve: {
students: function (StudentService, $q) {
var defer = $q.defer();
defer.promise.then(function () {
StudentService.getAllStudents(function (sts) {
alert(JSON.stringify(sts));
return sts;
});
})
defer.resolve();
}
}
})
The alert is returning data from the route successfully but not from the controller - i get an undefined in the controller:
paymentModule.controller('PaymentController', function($scope,students) {
alert(JSON.stringify(students));
Any help will be appreciated!
You should always return a promise to resolve functions, and, when creating a promise of your own, you should resolve it with the data you need to pass along with it.
.state('payment', {
url: '/payment',
templateUrl: 'frontend/components/payment/views/payment.html',
controller: 'PaymentController',
resolve: {
students: function (StudentService, $q) {
var defer = $q.defer();
//defer.promise.then(function () {
StudentService.getAllStudents(function (sts) {
//alert(JSON.stringify(sts));
//return sts;
defer.resolve(sts);
});
//})
//defer.resolve();
return defer.promise
}
}
})
I am trying to create a tag layout filled with categories, but I am not getting my Authentication because I am trying to resolve that service in my Router.
this is my Router code
(function () {
'use strict';
angular
.module('learningApp')
.config(sslRouter);
// Minification safe dependency Injection
sslRouter.$inject = ['$stateProvider'];
function sslRouter ($stateProvider) {
// SSL Route Definition
$stateProvider.state('ssl', {
parent: 'policy',
url: '/ssl',
data: {
roles: ['USER']
},
views: {
'policyConfig': {
templateUrl: 'components/configuration/service/policy/ssl/ssl.tpl.html',
controller: 'SSL'
}
},
resolve: {
'sslServiceData': function(sslService) {
return sslService.promise;
}
}
});
}
}());
This is my Service
(function() {
'use strict';
angular
.module('learningApp')
.factory('sslService', sslResource);
sslResource.$inject = ['Principal', '$resource', 'BASE_URL', 'exDomainService'];
function sslResource (Principal, $resource, BASE_URL, exDomainService) {
debugger;
var res = $resource(BASE_URL + '/api/companies/' + Principal.company() + '/sconfig/ssl/sslConfiguration', {}, {
query: {
method: 'GET',
isArray: false
},
update: {
method: 'PUT'
}
});
var data = {};
var servicePromise = _initService();
servicePromise.$promise.then(function (d) {
data = d;
if (!data.excludedCategories) {
data.excludedCategories = [];
}
if (!data.excludedDomains) {
data.excludedDomains = [];
}
exDomainService.tableData = getExcludedDomains();
});
function _initService () {
return res.query();
}
return {
promise: servicePromise,
rest: res
}
}
}());
This is my controller
(function() {
'use strict';
angular
.module('learningApp')
.controller('SSL', SSLController);
SSLController.$inject = ['$scope', 'sslService', 'preDefinedCategoryService', '$timeout', 'exDialog', 'exDomainService'];
function SSLController ($scope, sslService, preDefinedCategoryService, $timeout, exDialog, exDomainService) {
var vm = $scope;
/**
* #desc Flags for different type checks
* Booleans and Categories
*/
vm.flags = {
// By default true
enableInspectSSLTraffic: sslService.getSSlInspectionFlag(),
allowUntrustedCertificates: sslService.getUntrustedCertificatesFlag(),
allowHostnameMismatch: sslService.getHostnameMismatchFlag(),
selectedCategory: undefined,
initializing: true
};
vm.excludedCategories = sslService.getExcludedCategories();
vm.predefinedCategories = preDefinedCategoryService.rest.query();
vm.predefinedCategories.$promise.then(function() {
vm.categories = _processedCategories(vm.predefinedCategories, vm.excludedCategories);
});
}
}());
So basically problem is, I am getting Principal.Identity as undefined, but if I remove resolution from Router, I got identity but then I lose my data coming from service. I want my service to be loaded completely before its Controller, and I want my principal service to be loaded before service.
for Reference, This is my Principal Class
'use strict';
angular.module('learningApp')
.service('Principal',['$q', 'Account', 'localStorageService', function Principal($q, Account, localStorageService) {
var _identity,
_authenticated = false;
return {
isIdentityResolved: function () {
return angular.isDefined(_identity);
},
isAuthenticated: function () {
return _authenticated;
},
isInRole: function (role) {
if (!_authenticated || !_identity || !_identity.roles) {
return false;
}
return _identity.roles.indexOf(role) !== -1;
},
isInAnyRole: function (roles) {
if (!_authenticated || !_identity.roles) {
return false;
}
for (var i = 0; i < roles.length; i++) {
if (this.isInRole(roles[i])) {
return true;
}
}
return false;
},
company: function () {
debugger;
if (_identity) return _identity.companyId;
},
authenticate: function (identity) {
_identity = identity;
_authenticated = identity !== null;
},
identity: function (force) {
var deferred = $q.defer();
if (force === true) {
_identity = undefined;
}
// check and see if we have retrieved the identity data from the server.
// if we have, reuse it by immediately resolving
if (angular.isDefined(_identity)) {
deferred.resolve(_identity);
return deferred.promise;
}
// rather than retrieving from server, use cookie or whatever method
var cookieFound = UTIL.cookie("token");
if (cookieFound) {
var response = JSON.parse(JSON.parse(cookieFound));
var expiredAt = new Date();
expiredAt.setSeconds(expiredAt.getSeconds() + response.expires_in);
response.expires_at = expiredAt.getTime();
localStorageService.set('token', response);
}
// retrieve the identity data from the server, update the identity object, and then resolve.
Account.get().$promise
.then(function (account) {
account.data.roles = ["ADMIN", 'USER'];
account.data.langKey = "en";
_identity = account.data;
_authenticated = true;
deferred.resolve(_identity);
})
.catch(function() {
_identity = null;
_authenticated = false;
deferred.resolve(_identity);
});
return deferred.promise;
}
};
}]);
I am using the ui-router(http://angular-ui.github.io/ui-router/site/#/api/ui.router) solution for a form wizard and my state configuration looks like the following:
$stateProvider
.state('TabsView', {
url: '/mcm/:mcmcid',
controller: 'TabsController',
templateUrl: 'ngapps/mcm/views/TabsView.html'
})
.state('TabsView.Campaign Info', {
url: '/campaign-info',
templateUrl: 'ngapps/mcm/views/Campaign Info.html',
resolve: {
campaignFactory: 'CampaignFactory',
campaignData: function($stateParams,campaignFactory) {
return campaignFactory.getCampaignInfo($stateParams.mcmcid).$service;
}
},
controller: 'CampaignInfoController'
});
For the state "TabsView.Campaign Info" I try to resolve the campaignData by calling the CampaignFactory. The code for Campaign Factoy is as follows:
marketingCampaignModule.factory("CampaignFactory", ['AjaxFactory', '$q', function(AjaxFactory, $q) {
return {
getCampaignInfo: function(mcmcid) {
var result = {empty: true};
if (mcmcid > 0) {
var ajaxPromise = AjaxFactory.post("index.php/mcm/infosave/view", {mcmcid: mcmcid});
ajaxPromise.then(function(data) {
if (data['success']) {
if (data['params']) {
result = {'name': data['params']['name'], 'description': data['params']['description']};
}
}
return result;
});
}
}
};
}]);
campaignData in resolve does not get resolved. But I see that a call to the getCampaignInfo function of the CampaignFactory is being made in the console. I know I am doing something wrong with promise.Please tell me what am I doing wrong?
As per Chandermani's comment I modified the factory to return a promise as follows:
marketingCampaignModule.factory("CampaignFactory", ['AjaxFactory', '$q', function(AjaxFactory, $q) {
return {
getCampaignInfo: function(mcmcid) {
var deferred = $q.defer();
var result = {empty: true};
if (mcmcid > 0) {
var ajaxPromise = AjaxFactory.post("index.php/mcm/infosave/view", {mcmcid: mcmcid});
ajaxPromise.then(function(data) {
if (data['success']) {
if (data['params']) {
result = {'name': data['params']['name'], 'description': data['params']['description']};
}
}
deferred.resolve(result);
});
}else{
deferred.resolve(result);
}
return deferred.promise;
}
};
}]);
And modifed the resolve as follows:
resolve: {
campaignFactory: 'CampaignFactory',
campaignData: function($stateParams,campaignFactory) {
campaignFactory.getCampaignInfo($stateParams.mcmcid).then(function(data){
return data;
});
}
}
Still doesnt work. What am I doing wrong?
After the update you have done, you are just missing the return statement in resolve
campaignData: function($stateParams,campaignFactory) {
return campaignFactory.getCampaignInfo($stateParams.mcmcid);
}