I'm using the native AngularJS router and was wondering if there is a way to assign a controller to a route conditionally. For example, let's say I have three user types:
Guest
User
System Admin
When they come to the home page, I want to be able assign a different controller based on the user type. So I would have three registered controllers: guestHomeCtrl, userHomeCtrl, systemAdminHomeCtrl.
I imagined something like this:
$routeProvider
.when( '/' , {
controller: getHomeCtrl(),
controllerAs: 'homeCtrl'
})
I know I can just pass in the string of the registered controller, but the main issue is being able to find out what type of user is logged in. I have a userService that typically keeps track of that, but it doesn't seem like I can access it from where I set up the routes. Or am I mistaken?
Any direction would help out a lot.
I would suggest using userService with a single controller. Read through the page below, specifically the resolve argument.
https://docs.angularjs.org/api/ngRoute/provider/$routeProvider
This blog post also describes how to use the resolve.
http://odetocode.com/blogs/scott/archive/2014/05/20/using-resolve-in-angularjs-routes.aspx
Try sending the specific function or variable you need to the controller. I used userService.User.userAccountStatus, but it really depends on the setup in your service file.
$routeProvider
.when( '/' , {
controller: HomeCtrl,
controllerAs: 'HomeCtrl',
resolve: {
userService: function(userService) {
return userService.User.userAccountStatus();
}
}
})
I use ngInject for injecting dependencies, but I assume you get the gist of giving services to a controller.
angular
.module('app')
.controller('HomeCtrl', HomeCtrl)
/** #ngInject */
function HomeCtrl($scope, $log, $state, userService) {
}
I can provide further examples if you need them.
Related
I'm trying to create a BaseController which my controllers can extend to handle the history action for all models. Currently (for the other routes), I set it up like so:
$routeProvider.when('/', {
redirectTo: '/static/campaigns'
}).when('/static/campaigns/new', {
templateUrl: 'campaigns/new.html',
controller: 'CampaignNewController'
}).....
What I want to do for the history routes would be a general route which would cover all models, but I'm not sure if there's a way to use the route parameters within the setup like below.
when('/static/history/:model_name', {
templateUrl: model_name + '/history.html',
controller: model_name + 'Controller'
})
If you look at documentation :
https://docs.angularjs.org/api/ngRoute/provider/$routeProvider#when
you may notice that, templateurl can be a string or a function. Perhaps if you created a function on the right hand side of templateUrl and injected $routeParams and read the value of model_name and returned a string with model_name, it might just work.
You wont be able to do the same for controller; however, you will have to create a service, that takes model_name as input and does the same logic as multiple controllers would.
I want to display an HTML file when a user has logged in. Right now we have a slideshow that is presented to the user after logging in, but after it, I want to display another view.
I jumped on this project although I'm new to Angular and Ionic, I assume this is how we render out the slideshow:
In our controller, we have an IntroCtrl which operates the logic behind the slideshow. So, do I need to create another controller to display my view afterwards?
.controller('IntroCtrl', function ($scope, $state, $localStorage, $ionicSlideBoxDelegate, $ionicScrollDelegate, $stateParams) {
$scope.$on('$ionicView.enter', function (e) {
$ionicScrollDelegate.resize()
$ionicSlideBoxDelegate.slide(0, 1)
})
$scope.email = $stateParams.email
$scope.startApp = function () {
$localStorage.hasViewedSlideBox
$state.transitionTo('tab.dash')
}
$scope.next = function () {
$ionicSlideBoxDelegate.next();
}
})
I found this in our app.js and this file contains $stateProvider, $urlRouterProvider, $ionicConfigProvider.
At the bottom I found a lot of these:
.state('login', {
url: '/login',
cache: false,
templateUrl: 'templates/login.html',
controller: 'LoginCtrl'
})
Therefore I assume I should create a new one containing the templateUrl and controller of my view? I read online that these .state has to do with Angular routing, but I can be wrong.
However, I would be really happy if anyone could guide me here.
Like I said, I want to display a new view after the slideshow.
Thanks!
I suggest create a new html and design your "afterLogin" html and copy your state(to which you will be redirected after login), comment it out and change the templateUrl to your new html file.
That should do all what you want.
You don't need your IntroCrl in the new file because it will only run a slideshow which is not present.
But you should insert
$scope.startApp = function () {
$localStorage.hasViewedSlideBox
$state.transitionTo('tab.dash')
}
into your new controller.
If you don't have a route to which you are redirected after login, you have to provide more code, so we can dive more deep into it
I have an app which creates several surveys with random survey ids. As the ids are generated in the backend they are set in the controller. I read the documentation on that, however I do not really understand how to set the routeparams in order to always reach the page /survey/:surveryID.
Here is my code so far:
App Config:
...
.when('/survey/:surveyId', {
templateUrl: 'views/survey.html',
controller: 'SurveyCtrl',
controllerAs: 'survey'
})
Controller:
function SurveyCtrl($scope, RequestService, _, $location, $routeParams) {
$scope.go = function () {
$location.path('/#/survey/' + Math.random());
};
}
View with the link to /survey/:surveyId:
<div>
<md-button ng-click="go()">Enter Survey</md-button>
</div>
I know that this is not the right way and it is not even working. Can someone tell me how to dynamically create these params and set them in the controller so I can access the link with a button and then when clicked reach the survey/:surveyId page?
To get your work done,
$location.path('/survey/' + Math.random());
You can use search method to pass params as well,
$location.path('/myURL/').search({param: 'value'});
$location methods are chainable.
this produce :
/myURL/?param=value
You could also use the updateParams method for that:
$route.updateParams({'surveryID': Math.random()});
And access the data using $routeParams.surveryID
I have different views each created by a different controller. At a particular time only one of the views is visible.
I want to switch from one view to another view through a function of the controller of the first view and after that I want to call a method of the second view controller.
My problem is how should I call this method in an angular way?
I know the possiblity using $broadcast and $on but that smells a little bit.
The other choice ist to find the scope in the dom and calling the method via scope. But that is even more ugly.
What is the best solution?
You can use services to communicate between controllers. While you could create a generic shared service to have a central point to subscribe to and broadcast events, services are easier to maintain over time.
You can use Angular Routing
Check out the documentation. This is an excerpt from the documentation. You can make links like
Link
For the first route and so on.
phonecatApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'partials/phone-list.html',
controller: 'PhoneListCtrl'
}).
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: 'PhoneDetailCtrl'
}).
otherwise({
redirectTo: '/phones'
});
}]);
Okay it is done and simpler as expected.
The idea is to use a service used in both views (controllers), that contains a 'execution boolean'.
The first view set the boolean to true, the second set a watch on this boolean and therefore is called and can call the desired method.
In the service:
trigger: function(name) { model[name] = true; },
setTriggerWatch: function(scope, name, callback) {
scope.$watch(function value() {
return model[name];
}, function listener(newValue, oldValue) {
if (newValue) {
callback();
}
});
},
In the destination controller:
sessionData.setTriggerWatch($scope, 'createSession', function callCreateSession() {
_createSession();
});
In the source controller:
sessionData.trigger('createSession');
Let's say I have this config:
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'app/partials/index.html',
controller: 'defaultCtrl'
})
.when('/other', {
templateUrl: 'app/partials/other.html',
controller: 'errorCtrl'
})
.otherwise({
templateUrl: 'app/partials/404.html'
});
}
]);
I'm looking for a place to do some basic, common maintenance code before the router calls the route. Say I'd like to clear the console log via console.clear() every time the route is changed. How and where would be the best place in the code to do that?
The $route service raise events like $routeChangeStart which you can use to perform such tasks. You can implement them using the $scope.$on method. Someting like
$scope.$on('$routeChangeStart',function(angularEvent,next,current) {
//do you work here
});
Read the $route documentation to get idea on this and other such events.
Also $routeProvider configuration method when also can take a parameter resolve which actually is used to setup dependencies before the route is resolved. This resolve object map can also be used to achieve what you want to do.