Angular js trigger routing - javascript

I have a reset link, which is meant to reset my angular js app...
<a ng-click="resetApp()">reset</a>
I am handling the button press in the main controller...
$scope.resetApp = function(){
if(confirm("You will lose data...")){
$scope.user.reset();
// not sure how to do this in more angular js way
window.location = "/#";
}
}
I am not sure if setting the window.location as I have done is the right way to do things. It works for me, but does not seem like the correct way, and I have not been able to find out ow to do it online.

I have been using the so-called AngularJS way like this, at least the routing is handled by AngularJS rather than browser directly.
function Ctrl($scope, $location) {
$scope.resetApp = function(){
...
$location.url('/');
}
}
The path is what is defined in the Route Provider like this:
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'index.html',
controller: 'Ctrl'
}).
...

Related

Several angular modules for routing

Can i create several modules for routing in AngularJS app like:
1. First route management file:
angular.module('app.p.routes', ['ngRoute'])
.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when('/forbidden',
{
templateUrl: 'app/views/pages/forbidden.html'
})
.......................
2. Second route management file:
angular.module('app.admin.routes', ['ngRoute'])
.config(function ($routeProvider) {
$routeProvider
.when('/admin-dashboard',
{
templateUrl: 'app/views/pages/admin/dashboard.html',
controller: 'dashboardController',
controllerAs: 'dashboard'
})
.............................
3. Main app file:
angular.module('mainApp',
[
'ngAnimate', //animating
'app.p.routes', //public routing
'app.admin.routes',
'ui.bootstrap',
'ngParallax', //parallax effect
'ngFileUpload'
])
When i tried to use this approach page hangs and angular throws error:
> VM188:30554 WARNING: Tried to load angular more than once.
I need an approach to split public and admin routing management.
You can have as many AngularJS modules as you like. There are no rules against that, however, you've attempted to include the Angular source twice which is why you're seeing this warning...
> VM188:30554 WARNING: Tried to load angular more than once.
The simplest solution to your issue that I can think of, is to add an event listener to the $routeChangeStart event. With this you'll be able to verify that the current user has the correct permissions to view anything before they actually to do so.
A simple Service to store some basic information on the current user could like this.
var app = angular.module('app', ['ngRoute']);
app.service('AuthenticationService', function () {
// Set the User object
this.setUser = function () {
this.$user = user;
};
// Get the User object
this.getUser = function (user) {
return this.$user
};
});
And then upon receiving the $routeChangeStart event, you can retrieve the user object and confirm that they are allowed to proceed to the chosen resource.
Here's an example, whereupon a user needs to be an Administrator to view any route that has "/admin" in it.
app.run(function ($rootScope, $location, AuthenticationService) {
// Create a listener for the "$routeChangeStart" event
$rootScope.$on('$routeChangeStart', function () {
// Is the user is an Administrator? Are they attempting to access a restricted route?
if ($location.url().indexOf('/admin') && !AuthenticationService.getUser().isAdmin) {
// Redirect the user to the login page
$location.path('/login');
}
});
});
If you want a more advanced solution however, have a look at this: https://github.com/Narzerus/angular-permission
This will enable you to achieve a more in-depth ACL implementation across your application.

html5mode doesn't remove hashbangs

I have a gulp connect server running and want to remove hashbangs from the routeProvider I am using in my AngularJS project.
I have this in my app.js:
//Setting HTML5 Location Mode
companiesApp.config(['$locationProvider',
function ($locationProvider) {
$locationProvider.hashPrefix('!');
$locationProvider.html5Mode(true);
}
]);
I know that if I remove the hashPrefix it will work still with http://www.example.com/#example-uri but how do I get rid of that entirely. isn't html5Mode(true) supposed to do that?
Yes, $locationProvider.html5Mode(true); should do that.
But to be able to access pages directly from the browser, you should configure your server to redirect the request to the index page, then call the partial internally. Check this document on angular-ui documentation for how to configure the document to do so.
Try this if may be useful in your scenario
Add only has prefix like $locationProvider.hashPrefix('') to remove Bang prefix...
var app = angular.module('app', []);
app.config(['$routeProvider', '$locationProvider',
function ($routeProvider, $locationProvider)
{
$routeProvider.when('/', {
templateUrl: "app1.html",
controller: "App1Ctrl"
})
.when('/Program1', {
templateUrl: "app2.html",
controller: "App2Ctrl"
});
$locationProvider.hashPrefix("");
}
]);
first add $routeProvider in dependency and then add in last of hashPrefix is null
to remove tha bang prefix.

Stop Controller's activity when switch route

I create single page app by AngularJS and I found my problem. I have function refresh data every 2 minutes by jQuery in route A. When I change to other route, that function in controller is still working. This is my code.
App.js
var newsapp = angular.module('newsAppMD', ['ngRoute']);
newsapp.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/news', {
templateUrl: 'templates/news.html',
controller: 'imageNewsCtrl'
}).
when('/news/:nameCat', {
templateUrl: 'templates/news-thumbnail.html',
controller: 'newsPageCtrl'
}).
otherwise({
redirectTo: '/news'
});
}]);
newsapp.controller('imageNewsCtrl', function($scope, $http, $interval, $timeout ) {
$('#bottom-bar').find('#epg').hide();
$scope.updateTimeEPG = 120000;
$scope.fetchFeed = function() {
$http.get("http://wi.th/thaipbs_tv_backend/epg_forJS.php").success(function(response) {
$scope.items = response.Schedule;
console.log($scope.items);
$timeout(function() { $scope.fetchFeed(); }, $scope.updateTimeEPG);
}).then(function() {
$('#bottom-bar').find('.loading').hide();
$('#bottom-bar').find('#epg').show();
});
};
$scope.fetchFeed();
});
newsapp.controller('newsPageCtrl', function($scope, $http, $location) {
// blah blah blah
}]);
I choose /news imageNewsCtrl work. And when I switch to other route, function in imageNewsCtrl still work (I see function print console.log when I changed route). I want to stop function in controller when change route. Thanks for your suggestion everyone. :)
I am not too entirely sure, but try using $stateProvider instead of $routeProvider. If you do, then you need to npm install angular-ui-router (it is a powerful third party module) and replace ngroute. I only user $routeProvider for the .otherwise function. You can also do a lot more cool stuff like onEnter and onExit with $stateProvider. Another thing is I would recommend you to use only Angular instead of jQuery. I do not really see a point of you using both. Use Angular's two-way data binding! Also, if you really want to get into Angular, then I recommend John Papa's style guide. This guys knows what he is talking about for making a great Angular app. I hope this info helps!

Routing to non-Angular pages within Angular

I am converting a large server rendered app to use Angular. Because of the size, we are doing it a bit at a time. During this conversion period, part of the app will use Angular and part will not. This means that routing sometimes will route within the Angular app and sometimes it will need to transition from old world to new world (easy) or new world to old world (harder).
Ideally, I would like to specifically route some page transitions within the Angular app (new world) to the proper controllers but then any other page transitions should just fetch new HTML pages (old world).
I can't seem to figure out how to do this. I think I need to use the routeProvider and when / otherwise, but there isn't a lot of documentation that I found which is helpful.
You can't use routeProvider for the old world, since angular routes only direct you within the actual same page.
You could make a placeholder angular route for each legacy route, then in the controller, inject $window and do something like:
$window.location.href = destinationUrl;
Something like: (go to the old world on logout)
app.controller('LogoutCtrl', function ($scope, $window) {
var destinationUrl = 'https://mywebsite.com/';
$window.location.href = destinationUrl;
});
Vice versa, to go back to the angular world, just use a normal link to your angular route:
Link
If you want a catch-all route to redirect to the outside, you can do the following:
otherwise({
controller: 'NotFoundCtrl'
});
...
app.controller('NotFoundCtrl', function($scope, $location, $window) {
var path = $location.path();
$window.location.href="http://test.com" + path;
})
As triggerNZ said, you can always have a controller redirect unhandled routes to the outside. Here is the HTML and Javascript showing how to do it.
HTML
<div ng-app="myApp">
<script type="text/ng-template" id="this.html">
This Page.
</script>
<script type="text/ng-template" id="that.html">
That Page.
</script>
<div>
<ul>
<li>This</li>
<li>That</li>
<li>Other</li>
</ul>
<ng-view></ng-view>
</div>
</div>
Javascript
var app = angular.module("myApp", ['ngRoute']);
app.config(function ($routeProvider, $locationProvider) {
$routeProvider.when('/this', {
templateUrl: 'this.html'
}).when('/that', {
templateUrl: 'that.html'
}).otherwise({
template: "<div></div>",
controller: function ($window, $location, $rootScope) {
if (!$rootScope.isInitialLoad) {
$window.location.href = $location.absUrl();
}
}
});
$locationProvider.html5Mode(true);
});
app.run(function ($rootScope) {
$rootScope.$on('$routeChangeSuccess', function() {
$rootScope.isInitialLoad = (typeof $rootScope.isInitialLoad === "undefined");
});
});

Can angularjs routes have default parameter values?

Can I set a default value of a parameter of a route in AngularJS? Is there a way to have /products/123 and /products/ handled by the same route ?
I'm looking to refactor my existing code, which looks like:
myModule.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/products/', {templateUrl: 'products.html', controller: ProductsCtrl}).
when('/products/:productId', {templateUrl: 'products.html', controller: ProductsCtrl})
}]);
function ProductsCtrl($scope, $routeParams) {
$scope.productId = typeof($routeParams.productId) == "undefined" ? 123 : $routeParams.productId;
}
It works, but it's not very elegant. Is there a better way ?
I recognize that this question is old, but still: Why don't you just redirect the "empty" URL to one containing the default productId?
myModule.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/products/', {redirectTo: '/products/123'}).
when('/products/:productId', {templateUrl: 'products.html', controller: ProductsCtrl})
}]);
AngularJS does not allow default values for route parameters.
But routes (in AngularJS) should not have default parameters.
Resources could have default parameters.
In AngularJS if you want a route with an optional parameter, these are actually two different routes.
Why?
Routes should be simple
Routes does not allow regular expressions matching for parameters
Routes are not something which exposes an API to work in your application (unlike Resources do). Routes are just configuration which connects a URL with a template and a controller. Thus having more routes is better:
It is clear which route maps to which url.
It is more verbose, but simpler to read. Having more complex routes would create a steeper learning curve where AngularJS does not need one.
Unlike server-side frameworks which have routes
AngularJS routes do not have names.
You do not build URLs from the defined routes.
You do not have logic (a.k.a functions) in the routes definitions.
Simpler routes = more lines to define them = less headaches working with them.
NOTE: Please keep in mind the question and this answer are for an old version of AngularJS (1.0 I think) pre-dating the new routes/resources implementation.
I had a similar requirement. What i did was to create a function to resolve. Something like below
myModule.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/products/', resolveProduct()).
when('/products/:productId', resolveProduct())
}]);
function ProductsCtrl($scope, $routeParams) {
$scope.productId = $routeParams.productId;
}
function resolveProduct() {
var routeConfig = {
templateUrl: 'products.html',
controller: ProductsCtrl,
resolve: {
productId: ['$route', function($route){
var params = $route.current.params;
params.productId = params.productId || 123;
}]
}
}
return routeConfig;
}
With url: "/view/:id/:status?", You can indicate an optional parameter.
Just thought someone may need it.
Not sure if this question is specific to $routeProvider but in $stateProvider, you can achieve this by
myApp.config(function($stateProvider) {
$stateProvider
.state('products', {
url: '/:productId',
templateUrl: "/dashboard/products.html",
controller: 'ProductController',
params: {
productId: {
value: "defaultValue",
squash: true // or enable this instead to squash `productId` when empty
}
}
});
});

Categories