I am developing an application with angularjs what I need to do is to basically run some scripts when route is changed to a specific route I know that I can define a separate controller for each route. since, some routs are supposed to have shared data I shared a controller to between some of them
formApp.config(function($routeProvider) {
$routeProvider
.when('/firstUrl',{
templateUrl : 'firstURL',
controller : 'mainController'
})
.when('/secondURL' , {
templateUrl : 'secondURL',
controller : 'mainController'
})
}).run(function($rootScope, $location) {
$rootScope.$on("$routeChangeStart", function(event, next, current) {
if ( signed_in == false ) {
$location.path("/login");
}
});
});
The above is my config code,
MY QUESTION : I need to know if I can modify the code in the run() function, so that based on the route which user is redirected to some scripts are run.
or if this is not the right way to do that please correct me how do I have to solve this issue?
thanks in advance
I would recommend to create at least one controller per route. It makes the code more manageble.
Then you can define an init function that runs when each controller loads.
To share data between controllers you need to create a service, which is the correct way to do it rather then sharing the same controller for multiple paths.
It will also give you way more flexibilitywhen developing.
Update
Example
( Naming for example purposes only. Try to never do arrbitrary naming. )
#Service
angular.module('myService', [])
.factory('mSrv',[ function() {
return {
data: {
'first_name': 'John',
'last_name': 'Doe'
}
};
}])
;
#Controller1
angular.module('initMyCtrl1', ['myService'])
.controller('InitMyCtrl1', function( $scope, mSrv ) {
var initMyCtrl1 = function(){
console.log('runs on controller load')
console.log(mSrv.data);
};
initMyCtrl1();
})
;
#Controller2
angular.module('initMyCtrl2', ['myService'])
.controller('InitMyCtrl2', function( $scope, mSrv ) {
var initMyCtrl2 = function(){
console.log('runs on controller load')
console.log(mSrv.data);
};
initMyCtrl2();
})
;
Related
is there using angularJS 1.5 and ui.router to define State and routes dynamically?
I mean getting the data from a backend sever and then populate the ui-router param such as state, URL ...
I tried to use the put them in the run part but it's not working as the data retrieved from the server wasn't available when needed. here is what I'm doing
run(
function run(Idle, $http, $q, $state, $rootScope) {
Idle.watch();
$urlRouterProviderRef.otherwise('/login');
$urlRouterProviderRef.when("", "/login");
$http.get(_contextPath + '/routing', {})
.success(function(data)
{
$rootScope.LOGIN_PAGE_CONTROLLER_NAME = data.LOGIN_PAGE_CONTROLLER_NAME;
$rootScope.LOGIN_PAGE_PAGE_TITLE = data.LOGIN_PAGE_PAGE_TITLE;
$rootScope.LOGIN_PAGE_STATE = data.LOGIN_PAGE_STATE;
$rootScope.LOGIN_PAGE_TEMPLATE_URL = data.LOGIN_PAGE_TEMPLATE_URL;
$rootScope.LOGIN_PAGE_URL = data.LOGIN_PAGE_URL;
});
var test = $rootScope.LOGIN_PAGE_STATE;
$stateProviderRef.state($rootScope.LOGIN_PAGE_STATE, {
url : $rootScope.LOGIN_PAGE_URL,
views : {
"mainbody" : {
templateUrl : $rootScope.LOGIN_PAGE_TEMPLATE_URL
},
},
controller : $rootScope.LOGIN_PAGE_CONTROLLER_NAME,
data : {
pageTitle : $rootScope.LOGIN_PAGE_PAGE_TITLE,
authenticate : false
}
});
})
any help is really apreciated
The way to go is described here
AngularJS - UI-router - How to configure dynamic views
A code snippet:
var app = angular.module('app', ['ui.router.router']);
app.config(function($urlRouterProvider) {
// Prevent $urlRouter from automatically intercepting URL changes;
// this allows you to configure custom behavior in between
// location changes and route synchronization:
$urlRouterProvider.deferIntercept();
}).run(function($rootScope, $urlRouter, UserService) {
$rootScope.$on('$locationChangeSuccess', function(e) {
// UserService is an example service for managing user state
if (UserService.isLoggedIn()) return;
// Prevent $urlRouter's default handler from firing
e.preventDefault();
UserService.handleLogin().then(function() {
// Once the user has logged in, sync the current URL
// to the router:
$urlRouter.sync();
});
});
// Configures $urlRouter's listener *after* your custom listener
$urlRouter.listen();
});
Check more and working plunker there
I have this problem & I am unable to find the solution for it.
This is an example of code where I am trying to route to variable URL routing
$routeProvider.when('/Book', {
template: 'examples/book.html',
controller: BookCntl,
});
$routeProvider.when('/Book/chapter01', {
template: 'examples/chapter01.html',
controller: ChapterCntl,
});
If I want to fix the url till /Book/chapter and 01 can be a variable. Like if user changes 02 or 03 till 100. Do I need to write the $routeProvider 100 times or can be a simple solution, where I can use the number part as a variable and write single $routeProvider to handle 01 to 100?
No, you do not need to add 100 seperate route definitions. You add a variable to your url template by adding /:some_variable, and then you are to fetch that variable by using the $routeParams service.
Example
$routeProvider.when('/Book/chapter/:chapterid', {
templateUrl: 'examples/chapter-view.html',
controller: ChapterCntl,
});
And then inject $routeParams into your controller:
function ChapterCntl($routeParams) {
var chapterId = $routeParams.chapterid;
//use the id to fetch content.
}
It does seem like you have a different html page for each chapter. If that is the case you can set a function to the template field to generate the path for the html file:
$routeProvider.when('/Book/chapter/:chapterid', {
template: function(routeParams) {
var id = routeParams.id;
return 'examples/chapter'+id+'.html';
},
controller: ChapterCntl,
});
If that case is that you are fetching the data from an API through a service, it might be useful to be using the resolve field instead. The resolve field will loaded the data and be injectable into the controller. Which means that the data will be loaded before transitioning in to the new route.
$routeProvider.when('/Book/chapter/:chapterid', {
templateUrl: 'examples/chapter-view.html',
controller: ChapterCntl,
//Will run the below function before transitioning into new route.
resolve: {
chapter: function($routeParams, chaptersDataService) {
var id = $routeParams.chapterid;
return chaptersDataService.getChapter(id);
}
}
});
And the inject the chapter into your controller:
function ChapterCntl($scope, chapter) {
$scope.chapter = chapter;
console.log( chapter );
}
Have you considered UI Route Provider? You could easily use stateparams..
$stateProvider
.state('book.chapter', {
url: "/book/chapter/:chapterId",
templateUrl: 'book.chapter.detail.html',
controller: function ($stateParams) {
....
}
})
Sources:
https://github.com/angular-ui/ui-router/wiki/url-routing#url-parameters
http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$stateProvider
You could also stick with routeprovider in a slightly different way than suggested in other answers.
$routeProvider.when('/Book/:chapter', {
templateUrl : { function (dynamicUrl) {
return '/Book/' + dynamicUrl.chapter + '.html';
},
controller: 'ChapterCntl'
});
I don't understand why, but in Angular controller I have list, and if I success save file I want to go to another page and there show list of files which I save. I put name in list and everything is ok, but probably when I change html/root they deleted all list. I use same controller for two html page.
Controller:
$scope.imenaFajlova = [];
$scope.continueFileUpload=function (){
for (var i = 0;i<(file.files.length);i++) {
$scope.nameFile.push(file.files[i].name);
}
$http({
method: 'POST',
url: uploadUrl,
})
.success(function(data, status) {
document.getElementById("fromFileUpload").reset();
$location.path('/success');
})
.error(function(data, status) {
});
};
config:
uploadFile.config(['$routeProvider', function($routeProvider,$routeParams) {
$routeProvider
.when('/', {
templateUrl : 'resources/html/home.html',
controller : 'uploadFileController'
})
.when('/success', {
templateUrl : 'resources/html/success.html',
controller : 'uploadFileController'
})
.otherwise({
redirectTo: '/'
});
How can I send date to another view or save data when chanfe root url?
You should probably use a service that will handle this data move between pages, rather than using the same controller.
You can read here about services.
As others suggested you should use a factory or a service.
In case of a factory you first write a factory
angular
.module('myApp')
.factory('namesFactory', namesFactory);
function namesFactory() {
var names = [];
return {
pushNames: pushNames,
getNames: getNames
};
function pushNames(x) {
names.push(x);
}
function getNames() {
return names;
}
}
then you inject a factory dependency to your controller and use the methods from the factory inside your controller.
angular
.module('myApp')
.controller('NamesController', NamesController);
function NamesController($scope, namesFactory) {
namesFactory.pushNames("Ante");
console.log(namesFactory.getNames()); // prints ["Ante"] to the console
$scope.names = namesFactory.getNames();
}
For ng-repeat you would then use something like
<ul>
<li ng-repeat='name in names'>{{name}}</li>
</ul>
Using Same controller doesn't mean, it is sharing the same instance of the controller. They either need to have a common parent, which is not reinitialized, or store data in a factory/service and read it from there.
I'm fairly new to Angular and I'm wondering how to go about creating a list/detail view using Angular routes as what I currently have doesn't seem to be working.
The app has a list of 'projects' and when you click on a project you see a detailed view of that selected project, standard stuff. I've got this working using ng-switch but ideally I want to use seperate routes for the list/detail views. I've read that for this I'm going to need to use a factory method but I'm having difficulty passing the selected data between the routes. Here's what I have:
app.factory('Project', [ function ($rootScope) {
var _selectedProject = {};
_selectedProject.project = {};
return _selectedProject;
}]);
app.controller('GalleryController', ['$scope', function ($scope, _selectedProject) {
$scope.sharedProject = _selectedProject || {};
$scope.selectProject = function (proj) {
_selectedProject.project = proj;
};
$scope.$watch('sharedProject', function (proj) {
$scope.chosenProject = proj;
})
}]);
I'm actually getting cannot set property 'property' of undefined which is inside $scope.selectedProject.
A nice solution for this is ui-router.
ui-router allows the nesting of states which correspond to controllers, urls and html templates.
In your example I would do the following:
Install ui-router (described in the link above)
Apply a configuration as follows:
myApp.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('project', {
url: "/project",
templateUrl: "partials/project/list.html",
controller: project_list_controller
})
.state('project.details', {
url: "/details",
templateUrl: "partials/project/details.html",
controller: project_detail_controller
})
}
Split your current controller into a project list controller and a project details controller.
Finally I would use a service to store your selectedProject as its a singleton, see the correct useage and differences between services and factories in this helpful blog post
Hope this helps.
You named your factory Project but are using _selectedProject as the injection to controller. You also didn't include it in the injection array
Controller should look more like:
app.controller('GalleryController', ['$scope','Project', function ($scope, Project) {
$scope.sharedProject = Project || {};
$scope.selectProject = function (proj) {
Project.project = proj;
};
$scope.$watch('sharedProject', function (proj) {
$scope.chosenProject = proj;
});
}]);
I'm trying calling the /auth/logout url to get redirected after session is deleted:
app.config(['$routeProvider',function($routeProvider) {
$routeProvider
.when('/auth/logout',{
controller:'AuthLogout'
//templateUrl: not needed
})
})
.controller('AuthLogout', ['$window','$location', function ($window,$location) {
$window.localStorage.removeItem('user_username');
$window.localStorage.removeItem('user_id');
$window.localStorage.removeItem('user_session_token');
$location.path('/');
}]);
I actually don't need a view for AuthLogout controller but if I do not specify the templateUrl in routeProvider I can't get this to work, while if I specify a templateUrl it works.
How can I call the url/controller without to having to load a view??
You could do :
.when('/auth/logout', {
controller: function(){
//do staff
}
})
btw may be there is something wrong in your code
because template works and you could exploit it in
the same way
http://docs.angularjs.org/api/ngRoute/provider/$routeProvider
You can use a resolve handler according to the post https://github.com/angular/angular.js/issues/1838
Checkout this quick example and notice the alert statement in resolve.
http://jsfiddle.net/Wk7WD/34/
.when('/detail/:id/', {
resolve: {
load: function ($route, dataService) {
alert("hello");
//Your statements instead of all this which I found in an example
return dataService.load($route.current.params.id);
}
}
})
Instead of the alert you can have your own statements
use redirectTo
app.config(['$routeProvider',function($routeProvider) {
$routeProvider
.when('/auth/logout',{
redirectTo:'/'
})
});
Hope this will work for you :)