Several angular modules for routing - javascript

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.

Related

AngularJS undefined Controller using require

I am using requireJS in my application.
Whenever i tried to register controller on my module it said that the controller is not defined. Here is my controller which resides on login.controller.js
function LoginController() {
}
and here's my module code:
require('angular')
require('#uirouter/angularjs');
require('./service/storage')
require('./controller/login.controller')
angular.module('SecurityModule', ['ui.router'])
.controller('LoginController', LoginController);
// Routing
angular.module('SecurityModule')
.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.hashPrefix('');
$stateProvider.state('login', {
url: '/login',
templateUrl: '/app/resources/view/security/login.html',
controller: 'LoginController',
});
})
;
When i checked my bundled.js the declaration of LoginController appears first. So why is it still undefine?
Thanks.
NOTE that im using browserify (which then uses commonJS) to bundle my files.
As the documentation states:
A module is a collection of configuration and run blocks which get
applied to the application during the bootstrap process. In its
simplest form the module consist of collection of two kinds of blocks:
Configuration blocks - get executed during the provider registrations
and configuration phase. Only providers and constants can be injected
into configuration blocks. This is to prevent accidental instantiation
of services before they have been fully configured.
angular.module('myModule', []).
config(function(injectables) { // provider-injector
// This is an example of config block.
// You can have as many of these as you want.
// You can only inject Providers (not instances)
// into config blocks.
}).
run(function(injectables) { // instance-injector
// This is an example of a run block.
// You can have as many of these as you want.
// You can only inject instances (not Providers)
// into run blocks
});

getting data from a scrape on load

I am new to software development and am trying to build a fullstack javascript app on my own.
I currently am running a scrape with cheerio in express, as follows:
app.get('/scrape', function(req, res){
//do things.
})
I will be using Angular for the front end.
How do I do the scrape whenever a user visits my home page/root route, so that I have data to compare against their inputs in angular? assume that the home page is at '/'.
this is what my angular app.js looks like so far:
angular.module('FFTrades', [
'FFTrades.services',
'ngRoute'
]).config(function($routeProvider){
$routeProvider
.when('/', {
templateUrl: 'app/tradeanalyzer/tradeanalyzer.html',
controller: 'TradesController'
})
})
app.run will help you to check your url
app.run(function ($rootScope, $cookies, $location, $http) {
$rootScope.$on('$routeChangeStart', function (event, next, current) {
if (next.originalPath != '/') {
console.log('inside your home page');
}
});
});
You would want to use a .run module. These are run automatically when your app starts up.
And add your scrap data to a service or the $rootScope.
app.run(function($rootScope) {
$rootScope.hello = function() {
console.log('hello');
}
});
If you are new to angular you might run into some issues getting the result from the scrape promise and applying it to the $scope. These would be new questions, but above should answer the particular question you are looking for.

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");
});
});

unloading/destroying Angular lazy loaded components

I have a setup that is similar to the post found here http://ify.io/lazy-loading-in-angularjs/ to handle lazy loading various components of my app in Angular.
The problem I'm having is that the more components one loads, the memory footprint of the app grows (obvious, I know). Is there a clean way to 'unload' or 'destroy' angular services / controllers/ directives / etc that have been lazy loaded?
simple example (for reference)
app.js
var app = angular.module('parentApp', ['ui.router']).config(function ($stateProvider, $urlRouterProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
var app = angular.module('app', ['ui.router'])
.config(function ($stateProvider, $urlRouterProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
app.lazy = {
controller: $controllerProvider.register,
directive: $compileProvider.directive,
filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service
};
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.state('lazyLoad', {
url: '/lazyLoad',
templateUrl: 'views/lazyLoad.html',
controller: 'lazyLoadCtrl',
resolve: {
promiseObj: function ($q, $rootScope) {
var deferred = $q.defer();
var dependencies = [
'scripts/controllers/lazyLoad.js'
];
$script(dependencies, function () {
$rootScope.$apply(function () {
deferred.resolve();
});
});
return deferred.promise;
}
}
});
});
and the lazy loaded controller lazyLoad.js
angular.module('app')
.lazy.controller('lazyLoadCtrl', function($scope){
$scope.greeting = 'hi there';
}
);
If a user navigates to #/lazyLoad, the app will load in the controller (and view), and what ever else it is told it needs. But when the user navigates away from #/lazyload, I want all the previously loaded components to be unloaded / destroyed.
How would I entirely de-register / destroy / unload (not sure what the correct verb would be here...) the 'lazyLoadCtrl' controller. As stated above, Ideally I'd like to be able to unload the lazy loaded controllers, directives, filters, factories and services, once they are no longer needed.
Thanks!
Maybe you can try calling scope.$destroy()
From the angularjs scope doc https://docs.angularjs.org/api/ng/type/$rootScope.Scope
$destroy();
Removes the current scope (and all of its children) from the parent scope. Removal implies that calls to $digest() will no longer propagate to the current scope and its children. Removal also implies that the current scope is eligible for garbage collection.
The $destroy() is usually used by directives such as ngRepeat for managing the unrolling of the loop.
Just before a scope is destroyed, a $destroy event is broadcasted on this scope. Application code can register a $destroy event handler that will give it a chance to perform any necessary cleanup.
Note that, in AngularJS, there is also a $destroy jQuery event, which can be used to clean up DOM bindings before an element is removed from the DOM.

Angular js trigger routing

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'
}).
...

Categories