I code a lazyLoadModule function, which is used to loazyLoad angular.js modules.But I found that webpack will require all files in '../modules/' directory, the reason maybe is that var mod = require("../modules/" + module); executed. I want require files when call the function in router resolve.
lazyload.js:
exports.lazyLoadModule = function(module){
var resolver = {
'lazyLoad': ['$q', '$ocLazyLoad', function($q, $ocLazyLoad){
var deferred = $q.defer();
require.ensure([], function (require) {
var mod = require("../modules/" + module);
$ocLazyLoad.load({
name: mod.name,
});
deferred.resolve();
});
return deferred.promise;
}]
}
return resolver;
}
app.js:
var lazyLoadModule = require('../util/lazyLoad.js').lazyLoadModule;
angular.module('app', ['ui.router', 'oc.lazyLoad', 'ngMaterial']);
angular.module('app')
.config(['$stateProvider', '$urlRouterProvider', '$locationProvider',
function($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state('home', {
url: '/home',
template: require('../modules/home/template/home.html'),
resolve: lazyLoadModule('home/home.js')
})
.state('biz1', {
url: '/biz1',
template: require('../modules/biz1/template/biz1.html'),
resolve: lazyLoadModule('biz1/biz1.js')
})
$urlRouterProvider.otherwise('home');
$locationProvider.html5Mode(false);
$locationProvider.hashPrefix('!');
}
]);
angular.element(document).ready(function() {
angular.bootstrap(document, ['app'], {
});
});
You can use bundle-loader to do this:
(require('bundle?name=[path]!../modules/' + module))(function(mod) {
});
This will build every file inside the modules directory as a separate chunk, because of the name=[path] parameter.
Related
I have a problem, a Controller called OrderController standing on two modules, Sales and Supply. When I make the route that will use this controller as I can define which of the two controllers I want to use, how can I define which controller's module? I tried to register the route separately in each module, but still not the right.
Full code: https://plnkr.co/edit/iLUuUNKWZJhg23rrk1zB?p=preview
acmeModule.js
var app =
angular
.module('acme', [
// Angular UI
'ui.router',
// Acme modules
'acme.sales',
'acme.supply',
]);
app.config(config);
config.$inject = ['$stateProvider', '$urlRouterProvider'];
function config($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider
.state("home", {
url: "/home",
template: "Home"
})
}
salesModule.js
var app =
angular
.module('acme.sales', ['ui.router']);
app.config(config);
config.$inject = ['$stateProvider', '$urlRouterProvider'];
function config($stateProvider, $urlRouterProvider) {
$stateProvider
.state("orderBySales", {
url: "/orderBySales",
templateUrl: "content.html",
controller: 'OrderController',
controllerAs: 'vm'
});
}
app.controller('OrderController', OrderController);
function OrderController() {
var vm = this;
vm.Content = "Order by Sales";
}
supplyModule.js
var app =
angular
.module('acme.supply', ['ui.router']);
app.config(config);
config.$inject = ['$stateProvider', '$urlRouterProvider'];
function config($stateProvider, $urlRouterProvider) {
$stateProvider
.state("orderBySupply", {
url: "/orderBySupply",
templateUrl: "content.html",
controller: 'OrderController',
controllerAs: 'vm'
});
}
app.controller('OrderController', OrderController);
function OrderController() {
var vm = this;
vm.Content = "Order by Supply";
}
You have to name the controller differently, otherwise one controller overwrites the other one. In this constellation (plunker) it is the controller of module acme.supply.
Call it SupplyOrderController and SalesOrderController.
I am trying to utilise a factory within my ui-router resolve. I can see my factory name is returned, however the methods do not appeart to be there:
router.js
define(['module', 'require'], function(module, require) {
'use strict';
var Router = function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/shopping');
var userFactory = require('./common/user/userFactory');
$stateProvider
.state('shopping', {
url: '/shopping',
templateUrl: 'app/shopping.html',
resolve:{
"check":function(){
var something = userFactory;
console.log(userFactory.name);
console.log(userFcatory);
}
}
});
};
module.exports = ['$stateProvider', '$urlRouterProvider', Router];
});
When console.log'ing:
console.log(userFactory.name); //returns UserFactory
console.log(userFcatory); //returns:
Object {name: "UserFactory", component: Array[4]}
component:Array[4]
0:"$q"
1:"$http"
2:"$state"
3:($q, $http, $state)
length:4
__proto__:Array[0]
name:"UserFactory"
However my getData and useData methods do not seem to be available for me to use?
Fixed this by changing my router.js to:
define(['module', 'require'], function(module, require) {
'use strict';
var Router = function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/shopping');
var userFactory = require('./common/user/userFactory');
$stateProvider
.state('shopping', {
url: '/shopping',
templateUrl: 'app/shopping.html',
resolve:{
userFactory : 'UserFactory',
check:function(userFactory){
return userFactory.checkUser();
}
}
});
};
module.exports = ['$stateProvider', '$urlRouterProvider', Router];
});
I'm using AngularJS with RequireJS and ui-router, with the Play Framework 2.3 (and the WebJars stuff).
main.js
(function () {
'use strict';
requirejs.config({
// Packages = top-level folders; loads a contained file named 'main.js"
packages: ['dashboard'],
paths: {
'angular': ['../lib/angularjs/angular'],
'angular-ui-router': ['../lib/angular-ui-router']
},
shim: {
'angular': {
exports: 'angular'
},
'angular-ui-router': {
deps: ['angular'],
exports: 'angular'
}
}
});
require(['angular', 'angular-ui-router', './app'],
function (angular) {
var mod = angular.module('app', ['ui.router']);
mod.config(['$stateProvider', '$locationProvider', '$urlRouterProvider', function ($stateProvider, $locationProvider, $urlRouterProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
$urlRouterProvider.otherwise('/app/profile');
$stateProvider.state('profile', {
abstract: true,
url: '/app/profile',
templateUrl: '/views/app/content',
controller: 'AppController'
});
}]);
angular.bootstrap(document, ['app']);
});
})();
app.js
define(['angular', 'dashboard'], function(angular) {
'use strict';
return angular.module('app', ['app.dashboard']);
});
dashboard/main.js
define(['angular', './routes'], function(angular) {
'use strict';
return angular.module('app.dashboard', ['dashboard.routes']);
});
dashboard/routes.js
define(['angular'], function(angular) {
'use strict';
var mod = angular.module('dashboard.routes', []);
console.log("Enter the routes.js"); // DOES WORK
mod.config(['$stateProvider', function($stateProvider) {
console.log("Enter the config file in routes.js"); // DOESN'T WORK, NEVER REACH THAT POINT
$stateProvider.state('profile.dashboard', {
url: '',
templateUrl: '/views/app/dashboard'
});
}]);
return mod;
});
The states defined in my submodules are not loaded, but if I'm putting them in the main main.js, it does work :
mod.config(['$stateProvider', '$locationProvider', '$urlRouterProvider', function ($stateProvider, $locationProvider, $urlRouterProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
$urlRouterProvider.otherwise('/app/profile');
$stateProvider.state('profile', {
abstract: true,
url: '/app/profile',
templateUrl: '/views/app/content',
controller: 'AppController'
})
.state('profile.dashboard', {
url: '',
templateUrl: '/views/app/dashboard'
});
;
}]);
So this is really a problem about loading with RequireJS, but I can't figure out what's wrong..
Any ideas ? Thanks
Got Unknown provider when injecting service into the child state resolve function. But if defined a resolve in the parent state, it just works. Below there are some sample codes:
I defined a service module
angular.module('services', [])
.factory('myService', function() {
// my service here
})
and initialize the app
var app = angular.module('app', ['services', 'ui.router']);
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider,
$urlRouterProvider) {
$stateProvider.state('wizard', {
url: '/wizard',
abstract: true
})
.state('wizard.step1', {
url: '/step1',
templateUrl: ... ,
resolve: {
name: function(myService) {
// do something with mySerice
}
},
controller: function(name) {
// controller codes here
}
})
}]);
I got the error Unknown provider complaining about myService in the wizard.step1 resolve. But if I add a random resolve in the parent state, like
$stateProvider.state('wizard', {
url: '/wizard',
abstract: true,
resolve: {
a: function() { return 1; }
}
})
then it works without error. Wonder what happens here?
In your controller you have to inject your service MyService, so define something like this
.state('wizard.step1', {
url: '/step1',
templateUrl: ... ,
resolve: {
name: ['myService', function(myService) {
// do something with mySerice
}]
},
controller: ['name', function(name) {
// controller codes here
}]
})
You have to inject your service in your config function :
var app = angular.module('app', ['services', 'ui.router']);
app.config(['$stateProvider', '$urlRouterProvider', 'myService',
function($stateProvider, $urlRouterProvider, myService) {
...
Another way is to embed your resolve code in a service and assign directly the service :
app.config(['$stateProvider', '$urlRouterProvider' ,'mySuperService',function($stateProvider,
$urlRouterProvider, mySuperService) {
...
resolve: {
name: mySuperService()
}
.constant('mySuperService', function() {
var serv= function(){
// your code
}
return serv;
}
I have the below code. When I run my unit tests, I get that the resolve function is not code covered.
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/', {
controller: 'HomeCtrl',
resolve: {
homePage: function (homePageLoader) {
return homePageLoader();
}
},
templateUrl: 'views/home.html'
}).
otherwise({ redirectTo: '/' });
}]);
How do I write unit tests for the resolve function?
I had a smilar situation with my app.js with routeprovider & resolve. This was solved with below:
app.js
var appModule = angular.module('myApp',['ngRoute'])
.config(['$httpProvider', '$routeProvider', '$locationProvider', '$translateProvider', function ($httpProvider, $routeProvider, $locationProvider, $translateProvider) {
$locationProvider.html5Mode(true)
$routeProvider
.when('/services/main', {templateUrl: '/services/main/html/main.html', controller: 'MainCtrl', resolve: {
myVar: function (varService) {
return varService.invokeService();
}
}})
}])
Spec file
describe("Unit Testing: config - ", function() {
var appModule;
var mockService;
beforeEach(function() {
appModule = angular.mock.module("myApp");
});
it('should test routeProvider resolve', function() {
mockService = {
invokeService: jasmine.createSpy('invokeService').andReturn('myVar')
};
module(function($provide){
$provide.value('varService', mockService);
});
inject(function($route, $location, $rootScope, $httpBackend) {
$httpBackend.expectGET('/services/main/html/main.html').respond({});
$location.path('/services/main');
$rootScope.$digest();
expect($route.current).toBeDefined();
});
});
});
this ensures the coverage for the resolve.