Using ocLazyLoad to lazy load a controller with $stateProvider - javascript

I'm having issues using oclazyload with $stateProvider.
I have specified that the controller .js should be loaded in the router config, and it does,' but it's not available to use as an ng-controller attribute in the file loaded in templateURL.
ui-route config:
core
.run(
[ '$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}
]
)
.config(
[ '$stateProvider', '$urlRouterProvider',
function ($stateProvider, $urlRouterProvider) {
console.info('Routing ...');
$urlRouterProvider
.otherwise('/app/dashboard');
$stateProvider
.state('app', {
abstract: true,
url: '/app',
templateUrl: 'templates/app.html',
})
.state('app.orders', {
abstract: true,
url: '/orders',
templateUrl: 'templates/orders/orders.html',
})
.state('app.orders.index', {
url: '/index',
templateUrl: 'templates/orders/index.html',
resolve: {
deps: ['$ocLazyLoad',
function( $ocLazyLoad ){
console.info('Path ot order controller in route config',Momento.paths.js + 'controllers/orders/index.js');
return $ocLazyLoad.load([
Momento.paths.js + 'controllers/orders/index.js'
])
}
]
}
})
}
]
)
;
And my templateURL file starts:
<div class="" id="" ng-controller="OrdersIndexController">...</div>
But when it loads, console throws the error:
<info>orders/index controller loaded controllers/orders/index.js:3
<info>Now I've finished loading the controller/order/index.js config/ui-router.js:69
<info>orders template loaded VM30437:1 (<-- this is the app.orders abstract template with ui-view directive ready for app.orders.index view)
<error>Error: [ng:areq] Argument 'OrdersIndexController' is not a function, got undefined
... <trace>
So the file is loaded correctly by lazyload, confirmed by console output above and network tab in developer tools, but it's not available in the templateURL to use as controller? Does it need to be aliased either in router config using controller:'' key or in template? Does it need to be specifically attached to the (only) module in this app?
What am I missing?
PS: confirming that the name of the controller is in fact OrdersIndexController:
core
.controller('OrdersIndexController', [
'Model', '$scope', '$window',
function( Model, $scope, $window){
console.info("OrdersIndexController fired");
}
]);

You have to register your controller with
angular.module("myApp").controller
Working
angular.module("myApp").controller('HomePageController', ['$scope', function ($scope) {
console.log("HomePageController loaded");
}]);
Not working
var myApp = angular.module("myApp")
myApp.controller('HomePageController', ['$scope', function ($scope) {
console.log("HomePageController loaded");
}]);

Inside the function function($ocLazyLoad){} you must to declare the name of module that contains the controller and the name of file "to lazy load"
function( $ocLazyLoad ){
return $ocLazyLoad.load(
{
name: 'module.name',
files: ['files']
}
);
}

If you use the current documented way for ocLazyLoad 1.0 -> With your router
...
resolve: { // Any property in resolve should return a promise and is executed before the view is loaded
loadMyCtrl: ['$ocLazyLoad', function($ocLazyLoad) {
// you can lazy load files for an existing module
return $ocLazyLoad.load('js/AppCtrl.js');
}]
}
then in js/AppCtrl.js
You have something like this:
angular.module("myApp").controller('DynamicNew1Ctrl', ['$scope', function($scope) {
$scope.name = "Scoped variable";
console.log("Controller Initialized");
}]);
Note that with angular.module("myApp") you are attaching the new controller to an existing module, in this case the mainApp, so any of new dynamic controllers can use the app dependencies.
but you can define a new module an inject your dependencies, as described here, the later is used commonly when you estructure your app with a plugin architecture and you want to isolate the dynamic modules so they only have access to some especific dependencies

Related

any issues in this controller function?

when i use routers without controllers then my routers are working fine but when i add controllers in it. then my routers stop working... can anyone please tell me about my issues in routers functions?
LOGIN CONTROLLER:
angular.module('starter', ['ionic'])
.controller('LoginCtrl', function($scope, LoginService, $ionicPopup, $state) {
$scope.login = function() {
console.log("LOGIN user: " + $scope.username + " - PW: " + $scope.password);
LoginService.loginUser($scope.username, $scope.password).success(function(data) {
console.log("Login Successful");
$state.go('home');
}).error(function(data) {
var alertPopup = $ionicPopup.alert({
title: 'Login failed!',
template: 'Please check your credentials!'
})
})
}
});
ROUTERS CODE
angular.module('starter', ['ionic'])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'page2.html',
controller: 'HomeCtrl'
})
.state('login', {
url: '/login',
templateUrl: 'index.html',
controller: 'LoginCtrl'
})
$urlRouterProvider.otherwise('/login');
});
Your controller is wrongly declared. Remove injector from your module while creating controller. Something like
angular.module('starter')
.controller('LoginCtrl', function($scope, LoginService, $ionicPopup, $state) {
//...
});
Because of these reasons, it is best to have your module created in separate file. So you would have
module.js
angular.module('starter', ['ionic'])
config.js
angular.module('starter').config(function(){});
controller.js
angular.module('starter').controller('', function(){});
angular.module('starter', ['ionic'])
and
angular.module('starter')
are two entirely different concept . While [] converts the the method to a setter method. Meaning It will create a new instance of starter module. But if you do not use the third bracket it becomes a getter method meaning it will return already declared module.
Thats why you need to use
angular.module('starter').controller('', function(){});
for details look here
angular.module('starter', ['ionic']) ,
this code create an instance of angular app named starter. you should create an instance of an app only once. but you created twice here.
only use
angular.module('starter')
to use the app while declaring controller or config . but you should be careful that first create instance then use it.
that means
angular.module('starter', ['ionic'])
should use in the portion which will execute first .

How do you load service, resolve a function and pass data to controller through ocLazyLoad state?

In a $stateProvider state I want to:
Load a service JS file
Resolve a service function (API call)
Pass resulting data to controller
controllers/my-controller.js
angular.module('app').
controller('MyController', ['$scope', function($scope, serviceData){
console.log(serviceData)
}]);
config.js
...
.state('main', {
url: "/",
templateUrl: 'templates/my-template.html',
controller: 'MyController',
resolve: {
dependencies: ['$ocLazyLoad', function($ocLazyLoad) {
return $ocLazyLoad.load([
'controllers/my-controller.js'
])
}],
serviceData: ['$ocLazyLoad', '$injector', function($ocLazyLoad, $injector) {
return $ocLazyLoad.load('services/my-service.js')
.then(function(){
var $myService = $injector.get('MyService');
return $myService.GetData();
})
}]
}
})
I would expect the controller to console.log the data coming back from the API call that MyService does (not included for brevity, but that part works). Instead, I get undefined.
Any ideas?
Thanks!

How to annotate dependencies in an inline controller while configuring app routes?

I'm getting following error if I don't annotate the dependencies for an inline controller function for a route (I'm using strict DI mode and all other codes are annotated so that js-minification doesn't break my code):
https://docs.angularjs.org/error/$injector/strictdi?p0=function(AuthService,%20$state
Here is the logout route code:
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider', '$urlRouterProvider) {
$stateProvider.state('logout', {
url: '/logout',
controller: function(AuthService, $state) {
AuthService.logout();
$state.go('login');
}
}
}]);
Is there any technique to declare inline annotation for the above two dependent services (AuthService, $state) of the inline controller ?
I know the bellow work-around :
.state('logout', {
url: '/logout',
controller: LogoutController
});
function LogoutController (AuthService, $state) {
AuthService.logout();
$state.go('login');
}
LogoutController.$inject = ['AuthService', '$state'];
this works but just wanted to checkout if anyone knows any smart short-cut ?
Try
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider.state('logout', {
url: '/logout',
controller: ['AuthService', '$state', function(AuthService, $state) {
AuthService.logout();
$state.go('login');
}]
}
}]);
Not sure if that will work. Usually we separate our controllers into files for ease of use, rather than writing them inline in the config.route.js file.
Just to add more details here, this is expected for inline controllers.
See https://github.com/olov/ng-annotate/issues/50.
Either not inline them or add apply controller: /* #ngInject */ function(service1){ ... }.
The /* #ngInject */ tells ngannotate to apply annotation here.

AngularJS and RequireJS add controller to view

I have a problem with adding a Angular controller to my HTML view. The angular way of doing this is: ng-controller="<controller>". But because I am using RequireJs I have to do this in a different way. I have to add a sub page to every controller and view:
define(['app', 'login/LoginController'], function (app, LoginController) {
app.config(function ($routeProvider, $locationProvider) {
$routeProvider.when('/', {
templateUrl: "modules/" + 'login/login.html',
controller: LoginController
});
});
app.controller('LoginController', LoginController);
});
This way I can define my where my controller is and where my view is.
Problem
Now I have a header.html in which I want to include a menu.html. this can be done via: ng-include="'modules/menu/menu.html'". This works fine. But how can I add a controller to this menu.html?
I have tried: ng-controller="MenuController" but then I get the error: 'Error: [ng:areq] Argument 'MenuController' is not a function, got undefined'. So I do not know how I should add a controller to my menu.html with RequireJS.
MenuController
my MenuController looks as follows:
define(['$'], function ($) {
'use strict';
var MenuController = function ($location, menu, $scope) {
$scope.info="testing123";
};
return MenuController;
});
Anyone knows how I should do this?
You can for example use multiple views in the same controllerwith $stateProvider:
app.config(function ($stateProvider, $locationProvider) {
$stateProvider
.state('login', {
url: '/',
views: {
'menu': {
templateUrl: 'modules/menu/menu.html',
controller: MenuController
},
'login': {
templateUrl: 'modules/login/login.html'
controller: LoginController
}
}
});
});
Then in your template to call them you just need to do something like:
<div ui-view="menu"></div>
<div ui-view="login"></div>
You can see more info on github ui-router.

Can't lazy load controllers in angular with oc.lazyLoad - controller not found

I want to use lazy loading in my Angular project:
This is the relevant app.js code:
var app = angular.module('eva', ['ui.router',
'controllers', 'oc.lazyLoad']);
app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider', '$locationProvider', '$ocLazyLoadProvider',
function($stateProvider, $urlRouterProvider, $httpProvider, $locationProvider, $ocLazyLoadProvider) {
$httpProvider.interceptors.push('AuthInterceptor');
$urlRouterProvider.otherwise("/");
$locationProvider.hashPrefix('!');
$stateProvider.state('challenge', {
url: '/challenges',
templateUrl: 'views/Challenges.html',
controller: 'ChallengeCtrl',
onEnter: ['$state', 'auth', function($state, auth) {
if (!auth.isLoggedIn()) {
$state.go('login');
}
}],
resolve: { // Any property in resolve should return a promise and is executed before the view is loaded
loadMyCtrl: ['$ocLazyLoad', function($ocLazyLoad) {
// you can lazy load files for an existing module
return $ocLazyLoad.load('js/controllers/ChallengeController.js');
}]
}
This is my controller definition code:
angular.module('eva').controller('ChallengeCtrl', ['$scope', 'auth','$translate', 'challengeFactory', 'userFactory', 'userService',
function($scope, auth, $translate, challengeFactory, userFactory, userService) {
I am not loading the challengecontroller.js file in the index.html file.
I include oclazyload just before app.js in the index.html file:
<script type="text/javascript" src="js/lib/oclazyload/dist/ocLazyLoad.js"></script>
<script type="text/javascript" src="js/app.js"></script>
I get this error now when I run the app:
Error: [ng:areq] http://errors.angularjs.org/1.4.7/ng/areq?p0=ChallengeCtrl&p1=not%20a%20function%2C%20got%20undefined
I tried many things for lazy loading, none of them worked. Now I just followed the example on Example
I really am in a pickle here, and I have no clue what to do to get the lazy loading working. I rather not work with requirejs.
angular config is just a function, any dependencies should be already $inject before you call this config. you may include it in <script> tag and add it to app = angular.module['app', ['depend1'])
so you change it and try it again.
app.config(function($stateProvider, $urlRouterProvider, $httpProvider, $locationProvider, $ocLazyLoadProvider) {
btw: open your Browser Dev-Tools, to check whether this file js/controllers/ChallengeController.js is loadead correctly

Categories