routing sub-modules in angular - angularjs

how to write different modules with their own routing?
i have an angular app and it has different modules.i am going to write for each of them, specific route file, but i got this error
Uncaught Error: [$injector:unpr] http://errors.angularjs.org/1.6.4/$injector/unpr?p0=routeServiceProvider%20%3C-%20routeService
it is my code :
sample.module.js
angular.module('app.sample', []);
sample.route.js
angular
.module('app.sample')
.run(appRun);
/* #ngInject */
function appRun (routeService) {
routeService.configureRoutes(getRoutes());
}
function getRoutes () {
return [ {
url: '/sample',
config: {
templateUrl: 'sample.html'
}
}
];
}
i already add ngRoute and inject these files in index.html file

To achieve such project structure, ui-router is the best way to go. It is a separate library so you have to include into your project as a dependency.
Here are the snippets that will be useful for your case
dashboard.module.js
angular.module('app.dashboard', ['ui.router']);
dashboard.router.js
angular.module('app.dashboard')
.config(routerConfig);
routerConfig.$inject = ['$stateProvider'];
function routerConfig($stateProvider) {
$stateProvider
.state('state1', {
url: '/state1',
templateUrl: 'url/to/state1.html',
controller: function () {
// controller code here
}
})
.state('state2', {
url: '/state2',
templateUrl: 'url/to/state2.html',
controller: function () {
// controller code here
}
});
}
sample.module.js
angular.module('app.sample', ['ui.router']);
sample.router.js
angular.module('app.sample')
.config(routerConfig);
routerConfig.$inject = ['$stateProvider'];
function routerConfig($stateProvider) {
$stateProvider
.state('state3', {
url: '/state3',
templateUrl: 'url/to/state3.html',
controller: function () {
// controller code here
}
})
.state('state4', {
url: '/state4',
templateUrl: 'url/to/state4.html',
controller: function () {
// controller code here
}
});
}
Lastly, app.module that connects all these modules
app.module.js
angular.module('app', [
/*
* sub-modules
*/
'app.dashboard',
'app.sample'
]);
To sum up, you have two independent sub-modules (app.dashboard and app.sample) with their own routing logic and one module (app) that wraps them into one angular application.
$stateProvider, service provided by ui.router, is used for registering states.
Additional info
Since your application is modular, you are probably going to need nested routing which is greatly supported by ui.router. Read docs to get more information on nested states.
Update
However, if you still want to stick with ngRoute, this and this clearly explain how to achieve the same result.

Related

Using angular routeProvider with controller

Please consider the this code where the routeProvider is needed to inject page(n).html in ng-view.
In addition to the console error:
unknown provider: $routeProviderProvider <- $routeProvider
The argument to function routeIt is the name of the page to navigate to, How can I mix a conditional switch with routeProvider.when in order to call the page matching the argument in the most efficient manner? Thanks
(function () {
'use strict';
angular
.module('appModule')
.controller('MainMenuCtrl', ['$scope', '$http', 'TogglerFactory', '$routeProvider', MainMenuCtrl]);
function MainMenuCtrl($scope, $http, Toggler, routeProvider) {
$http.get('models/mainMenu.json').then(
function (response) {
$scope.menuItems = response.data;
},
function (error) {
alert("http error");
}
)
function routeIt (page) {
routeProvider
.when('/page1', {
url: "/page1",
templateUrl: 'views/page1.html',
controller: 'Page1Ctrl'
})
.when('/page2', {
url: "/page2",
templateUrl: 'views/page2.html',
controller: 'Page2Ctrl'
})
}
$scope.itemClicked = function (item){
Toggler.menuToggle();
routeIt(item);
}
}
})();
Service providers aren't available for injection in run phase (i.e. anywhere but provider services and config blocks). It is possible to make route provider injectable and configure it after config phase,
app.config(function ($provide, $routeProvider) {
$provide.value('$routeProvider', $routeProvider);
});
And controllers aren't the best places to implement any logic (e.g. route hot-plug).
Ok you're using your routeProvider wrong you need to configure your routes inside .config blocks
angular.module('myApp', [])
.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/page1', {
url: "/page1",
templateUrl: 'views/page1.html',
controller: 'Page1Ctrl'
}
})
If you want to change the url from your controller use $location.path('/page1'); inside your controller.

angular-ui: how to get data from "resolve" option when using $stateProvider.state

The docs and stuff I've seen show how to use the "resolve" option but how do you get the data back?
I'm using meanjs.org v0.3.x
My route:
//Setting up route
angular.module('mymodule').config(['$stateProvider',
function($stateProvider) {
//start routing
$stateProvider.
state('some-path', {
url: '/some-url',
templateUrl: 'modules/mymodule/views/my-controller.client.view.html',
resolve: {
DataService: 'DataService',
promiseToResolve: function(DataService){
return DataService.get({});
}
}
});
}
]);
Now how exactly to I access the "promiseToResolve" data in my controller? Docs don't seem to mention this.
Also, please let me know if the above code would break when it is minified.
angular.module('mymodule').config(['$stateProvider',
function($stateProvider) {
//start routing
$stateProvider.
state('some-path', {
url: '/some-url',
templateUrl: 'modules/mymodule/views/my-controller.client.view.html',
controller: mySpecialController,
resolve: {
promiseToResolve: ['DataService', function(DataService) {
return DataService.get({});
}]
}
});
}
]);
You don't need the specific DataService line, so it's removed, and now in your controller (which you've specified in the above code) you can directly access the resolved data:
angular.module('mymodule').controller('mySpecialController', ['$scope', 'promiseToResolve',
function ($scope, promiseToResolve) {
$scope.dataResults = promiseToResolve.data;
}
]);
As for minification, here we use ngInject which is great.

Separate common parts of controller into a common controller

I'm developing an web app using AngularJS with uiRouter. I developed my route configuration as follows:
(function () {
'use strict';
var module = angular.module('app', ['ngMaterial', 'ui.router']);
function Config($urlRouterProvider, $stateProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider.state('Home', {
url: '/',
templateUrl: 'Partials/homeview.html',
controller: 'homeCtrl'
}).state('Table', {
url: '/tableview',
templateUrl: 'Partials/tableview.html',
controller: 'tableCtrl'
}).state('List', {
url: '/listview',
templateUrl: 'Partials/listview.html',
controller: 'listCtrl'
}).state('New', {
url: '/new',
templateUrl: 'Partials/new.html',
controller: 'newCtrl'
}).state('Edit', {
url: '/edit/:index',
templateUrl: 'Partials/edit.html',
controller: 'editCtrl'
});
}
Config.$inject = ["$urlRouterProvider", "$stateProvider"];
module.config(Config);
}());
The thing in some controller passed to the view the code is duplicated, so I would like to know if there is a way to pass 2 controllers to the view at the same time or if there is a way to create a separate file with that specific part of the duplicated controller and pass it as Dependency Injection in the desired controllers.
You can't have two controllers linked to a uiRouter route. But you could certainly make a service or factory that includes your universal functionality. (See angular.service vs angular.factory for more research.)
var app = angular.module('app',[])
app.service('myFunctions',function() {
this.addNumbers = function(a,b) {
// calculate some stuff
return a+b;
}
}
app.controller('myController',function(myFunctions){
myFunctions.addNumbers(2,2); // 4
})

how does todo mvc example for angularjs do without ng-controller?

Every example I've looked at has made use of the ng-controller directive to get things working.
The Todo MVC example at https://github.com/tastejs/todomvc/tree/gh-pages/examples/angularjs creates a 'TodoCtrl' controller. But in the corresponding index.html, there is no use of the ng-controller directive.
How is this possible? and why did they choose to do it this way?
It uses the ngRoute provider.
angular.module('todomvc', ['ngRoute'])
.config(function ($routeProvider) {
'use strict';
var routeConfig = {
controller: 'TodoCtrl',//add controller to view
templateUrl: 'todomvc-index.html',
resolve: {
store: function (todoStorage) {
// Get the correct module (API or localStorage).
return todoStorage.then(function (module) {
module.get(); // Fetch the todo records in the background.
return module;
});
}
}
};
$routeProvider
.when('/', routeConfig)
.when('/:status', routeConfig)
.otherwise({
redirectTo: '/'
});
});

Angular.js configuring ui-router child-states from multiple modules

I'd like to implement a setup where i can define a "root state" in the main module, and then add child states in other modules. This, because i need the root state to resolve before i can go to the child state.
Apparently, this should be possible according to this FAQ:
How to: Configure ui-router from multiple modules
For me it doesn't work:
Error Uncaught Error: No such state 'app' from ngBoilerplate.foo
Here is what i have:
app.js
angular.module( 'ngBoilerplate', [
'templates-app',
'templates-common',
'ui.state',
'ui.route',
'ui.bootstrap',
'ngBoilerplate.library'
])
.config( function myAppConfig ( $stateProvider, $urlRouterProvider ) {
$stateProvider
.state('app', {
views:{
"main":{
controller:"AppCtrl"
}
},
resolve:{
Auth:function(Auth){
return new Auth();
}
}
});
$urlRouterProvider.when('/foo','/foo/tile');
$urlRouterProvider.otherwise( '/foo' );
})
.factory('Auth', ['$timeout','$q', function ($timeout,$q) {
return function () {
var deferred = $q.defer();
console.log('before resolve');
$timeout(function () {
console.log('at resolve');
deferred.resolve();
}, 2000);
return deferred.promise;
};
}])
.run(function run( $rootScope, $state, $stateParams ) {
console.log('greetings from run');
$state.transitionTo('app');
})
.controller( 'AppCtrl', function AppCtrl ( $scope, Auth ) {
console.log('greetings from AppCtrl');
});
foo.js
angular.module( 'ngBoilerplate.foo', ['ui.state'])
.config(function config( $stateProvider ) {
$stateProvider
.state( 'app.foo', {
url: '/foo/:type',
views: {
"main": {
controller:'FooCtrl',
templateUrl: function(stateParams) { /* stuff is going on in here*/ }
}
}
});
})
.controller( 'FooCtrl', function FooCtrl( $scope ) {
console.log('deferred foo');
});
How do i make this work or what other approaches could i take to have something global resolved before every state (without defining a resolve on each state)?
I finally chose this approach which does the job for me:
// add all your dependencies here and configure a root state e.g. "app"
angular.module( 'ngBoilerplate', ['ui.router','templates-app',
'templates-common','etc','etc']);
// configure your child states in here, such as app.foo, app.bar etc.
angular.module( 'ngBoilerplate.foo', ['ngBoilerplate']);
angular.module( 'ngBoilerplate.bar', ['ngBoilerplate']);
// tie everything together so you have a static module name
// that can be used with ng-app. this module doesn't do anything more than that.
angular.module( 'app', ['ngBoilerplate.foo','ngBoilerplate.bar']);
and then in your app index.html
<html ng-app="app">
In the documentation the feature1 module depends on the application module. Try
angular.module( 'ngBoilerplate.foo', ['ngBoilerplate'])
I would of just commented but i do not have the rep. I know this is old but i had the same problem and came across this. One thing i am confused about is in app.js you do not import "ngBoilerplate.foo" but ngBoilerplate.library instead. I had the same problem and my solution was to inject sub modules into the top module instead of their parent.
My structure was module('ngBoilerplate'), module('ngBoilerplate.foo') and module('ngBoilerplate.foo.bar')'. I was injecting ngBoilerplate.foo.bar into ngBoilerplate.foo and the $stateProvider was failing. I needed to inject ngBoilerplate.foo.bar into top level ngBoilerplate.
I thought i would put this here in case anyone else sees this. The error i had was Uncaught TypeError: Cannot read property 'navigable' of undefined from ngBoilerplate.foo

Resources