How to call function inside ui-route state - angularjs

I am new to angular,i need know how to call function next to the roles instead of [] need to call function , in the below example:-
state('signin', {
parent: 'site',
url: '/signin',
data: {
roles: [] //Here i need to call function Becuase i need
assign values like this roles: ['dev','Admin']
(need to know how to call function here)
},
views: {
'': { templateUrl: '/signin.html' },
'content#': {
templateUrl: '/index.html',
controller: 'SigninCtrl'
}
}
})
If , i am trying with resoleve like below example:-
.state('signin', {
parent: 'site',
url: '/signin',
views: {
'': { templateUrl: '/signin.html' },
'content#': {
templateUrl: '/index.html',
controller: 'SigninCtrl'
}
},
resolve: {
TrackerApp: function ($q) {
var defer = $q.defer();
roles: Loadrole()
defer.resolve();
return defer.promise();
}
}
})
Getting Error like:-
TypeError: Cannot read property 'roles' of undefined
if am putting roles inside resolve getting above error

Your resolve method must be like this:
resolve: {
"trackerApp" : "TrackerApp",
"roles" : trackerApp.getRoles();
}
Move the data fetching part to service method like getRoles(). Assign it to roles property which will be available in your controller scope.

Related

How to modify url of a state in AngularJS ui-routes

I am on angular 1.6. Trying to override value of a ui-router state.
Initial states as follows :
$stateProvider.state('parent', {
abstract: true,
parent: 'ancestor',
url: '/parent',
data: {
authorities: [A,B]
},
views: {
'content#': {
templateUrl: 'app/scripts/myapp/module/parent.html'
}
}
})
.state('child', {
parent: 'parent',
abstract: true,
views: {
'tabs': {
templateUrl: 'app/scripts/myapp/module/submodule/child.html',
controller: 'ChildController',
controllerAs: 'childController'
}
}
})
.state('grandChild', {
parent: 'child',
url: '/{dataSource:(?:option1|option2|option3)}',
views: {
'body': {
templateUrl: 'app/scripts/myapp/module/submodule/grandchild.html',
controller: 'GrandChildController',
controllerAs: 'grandChildController'
},
},
resolve: {
groups: ['MyService', '$transition$', function (MyService, $transition$) {
var selectedSource = $transition$.params().dataSource ? $transition$.params().dataSource : 'option1';
return MyService.getGroups(selectedSource);
}]
}
})
Then in one of sub-implementation I am trying to override value of url - adding option4 for one of the state.
var states = $stateRegistry.deregister('grandChild');
$stateRegistry.register(states[0]);//There is one more child. For simplicity not showing here.
states[1].url.pattern = '/{dataSource:(?:option1|option2|option3|option4)}';
$stateRegistry.register(states[1]);
when I do following on 'grandChild'
$state.go('grandChild', {dataSource: 'option4'});
I get error as
Param values not valid for state 'grandChild'. Invalid params: [ dataSource ]
when I inspect $state
I see something weird.
$state.$current.params.datasource.type.pattern = /(?:option1|option2|option3)/
$state.$current.url.pattern = "/{dataSource:(?:option1|option2|option3|option4)}"
$state.$current.url._compiled[0] = /((?:option1|option2|option3))/

How to use params without showing in url?

controllerA from state A
$state.go('account.accountRegister', {accountType: $stateParams.accountType, acName: acName})
State defined in app.js
.state('account.accountRegister', {
url: '/:accountType/register',
params: {accountType, acName},
views: {
'mainView#':{
templateUrl: 'app/views/registration.html',
controller: 'registrationController'
}
}
})
controllerB from state B
console.log($stateParams.acName); // is getting undefined
How to use acName in the controller without showing in the url part of the state?
I came up with a solution
.state('account.accountRegister', {
url: '/:accountType/register',
params: {
acName: {
value: 'defaultValue',
squash: false
}
},
views: {
'mainView#':{
templateUrl: 'app/views/registration.html',
controller: 'registrationController'
}
}
})
For more info on squash property of the params object:
https://ui-router.github.io/docs/0.3.1/#/api/ui.router.state.$stateProvider

Angular ui-router resolve not working

I am trying to load a get service JSON function in the main state resolve function so I can store the data to a scope variable.
The account JSON information is relevant because all sub pages are essentially dependent on the information.
--
The below code is partially working. The account resolve function is being successfully called and even the $http returns a promise (state === 0 though). The issue is when the account function resolves the state.controller is never being called.
$stateProvider
.state('app',{
url: '/',
views: {
'header': {
templateUrl: '../views/templates/partials/header.html',
},
'content': {
templateUrl: '../views/templates/partials/content.html'
},
'footer': {
templateUrl: '../views/templates/partials/footer.html',
}
},
resolve: {
account: function($timeout, accountFactory){
//Comment
return $http({method: 'GET', url: '/account.json'});
}
},
controller: ['$scope', 'account', function($scope, account){
// You can be sure that promiseObj is ready to use!
$scope.data = account;
console.log('SCOPE!!!!!');
}],
})
.state('app.accessory', {
url: 'accessory',
views: {
'content#': {
templateUrl: '../views/accessory/listing.html',
controller: 'accessoryListingCtrl',
controllerAs: 'vm'
}
}
})
}]);
Your parent state config is not correct. When using multiple named views A controller does not belong to a state but to a view, so you should move your controller statement to the specific view declaration, or all of them if you need it everywhere.
See here: https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views
$stateProvider
.state('report',{
views: {
'filters': {
templateUrl: 'report-filters.html',
controller: function($scope){ ... controller stuff just for filters view ... }
},
'tabledata': {
templateUrl: 'report-table.html',
controller: function($scope){ ... controller stuff just for tabledata view ... }
},
'graph': {
templateUrl: 'report-graph.html',
controller: function($scope){ ... controller stuff just for graph view ... }
},
}
})
I don't know why the controller does not get called. But you can start by making sure that resolve always return data.
resolve: {
account: function($timeout, accountFactory){
//Comment
return $http({method: 'GET', url: '/account.json'})
.$promise.then(
function(data) { return data; },
function(error) { return error; });
}
}

Angularjs ui-router abstract state with resolve

Is it possible to make an abstract state with ui-router that needs to resolve data? I need to load the top half of a page with profile info, and then have a sub-nav that loads other details at the bottom of the page. The idea is that the abstract state would load the profile info every time regardless of which child state I am on. It doesn't seem to work.
Example:
.state('app.profile', {
abstract: true,
url: 'user/:username',
views: {
content: {
templateUrl: 'views/frontend/profile.html',
controller: 'ProfileCtrl',
resolve: {
data: ['$stateParams', 'ProfileService', function ($stateParams, ProfileService) {
var username = $stateParams.username;
return ProfileService.getProfile(username);
}]
}
}
}
})
.state('app.profile.something', {
url: '',
views: {
profile: {
templateUrl: 'views/frontend/profile.something.html',
controller: 'ProfileCtrl',
resolve: {
data: ['$stateParams', 'ProfileService', function ($stateParams, ProfileService) {
var username = $stateParams.username;
return ProfileService.getProfileSomething(username);
}]
}
}
}
})
Solution here is to distinguish the names of the resolved data. Check this answer:
angular ui-route state parent and resolve (nested resolves)
And its plunker
So in our case we would need this change in parent
resolve: {
dataParent: ['$stateParams', 'ProfileService', function ($stateParams, ProfileService) {
var username = $stateParams.username;
return ProfileService.getProfile(username);
}]
}
and this in child
resolve: {
dataChild: ['$stateParams', 'ProfileService', function ($stateParams, ProfileService) {
var username = $stateParams.username;
return ProfileService.getProfileSomething(username);
}]
}
so, instead of working with resolve : { data: ... } in parent and child we would have these:
// parent state
resolve : { dataParent: ... }
// child state
resolve : { dataChild: ... }
One working example should be better than other words...

Using an Angular factory for route resolves

Using UI-Router, but I'm not sure that it matters.
What I'm trying to do is extract away my current resolve logic into a factory/service, such that it doesn't pollute my $stateProvider definition. This is a short example:
Here's my current config: ($kinvey is a service that returns a promise)
.state('home', {
url: '/',
views: {
'header': headerView,
'content': {
templateUrl: 'views/main.html',
controller: 'MainCtrl',
},
'footer': footerView
},
resolve: {
user: ['$kinvey', function ($kinvey) {
return $kinvey.User.me();
}]
}
})
And what I'd like it to be:
resolve: {
'user': 'DataResolverService.userResolve'
}
DataResolverService
.factory('DataResolverService', function DataResolverService($kinvey) {
var userResolve = {
user: ['$kinvey', function ($kinvey) {
return $kinvey.User.me();
}]
};
// public API
return {
userResolve: userResolve
};
});
I seem to be getting a Unknown provider: DataResolverService.userResolveProvider <- DataResolverService.userResolve. Is this because factories/services can't be run like this inside the config() block?
This is because you are using a service in the config block. You should be able to inject it like this:
resolve: {
'user': ['DataResolverService', function(DataResolverService){
return DataResolverService.userResolve;
}]
}
An alternative approach would be to hide the injection mess in a constant (don't forget to include $injector as a dependency):
resolve: $injector.get('ResolveMap')
app.constant('ResolveMap',{
'user': ['DataResolverService', function(DataResolverService){
return DataResolverService.userResolve;
}]
});
There was a discussion around this here: https://groups.google.com/forum/#!topic/angular/QtO8QoxSjYw

Resources