How to load a directive into a module after instantiating using requirejs - angularjs

To describe my hurdle, A little back story. I was injecting all the requirejs path files(directives basically) which contains any directive to my main module in the app.js, which was working perfect. Its somewhat like
define(['angularAMD', 'angular-route', 'angular-resource', 'angularTranslate', 'angularTranslateLoaderStaticFiles', 'bootstrap', 'angular-idle', 'loadingMaskDirective', 'multiselectDirective', 'treeview.directive', 'tabs', 'checklist.directive'], function(angularAMD) {
var app = angular.module("myApp", ["ngRoute", "ngResource", "ngTable", "myApp.directives", 'ui.bootstrap', 'flow']);
app.config(....){
/**some route provider**/
}...
angularAMD.bootstrap(app);
return app;
I have defined all directives and also injected them to main module. But I want to define some directive in their indivisual controller to reduce initial load. There has to be some method. Right !!
And code in my directive js files looks like..
define(['angular'], function() {
angular.module('myApp').directive('SomeDirective',
['$parse', '$compile', '$rootScope', '$filter', function($parse, $compile, $rootScope, $filter) {
.........
So, when I try to define the same in page controller not in app.js, It doesn't work. However I am amazed that the factory function in this case works but not directive.
Any help will be appreciated. Thanks

Have you tried to use app to create the directive?
define(['app'], function(app) {
app.directive('SomeDirective',
['$parse', '$compile', '$rootScope', '$filter', function($parse, $compile, $rootScope, $filter) {
.........
An alternative provided by angularAMD is:
define(['angularAMD'], function(angularAMD) {
angularAMD.directive('SomeDirective',
['$parse', '$compile', '$rootScope', '$filter', function($parse, $compile, $rootScope, $filter) {
.........
The benefit of 2nd approach is to allow loading of directive before loading of your app.js. See Loading Application Wide Module for more detail.

Related

Angular depandency problems at minify compiling

I have an app which uses a lot of different js files. When I compile the app normaly with gulp everything works well, but when I compile everything in one file to minify it, I get an error (Uncaught Error: [$injector:modulerr]).
app-55bb2aca73.js:4 Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.5.8/$injector/modulerr?p0=app&p1=Error%3A%20%…http%3A%2F%2Flocalhost%3A8080%2Fbuild%2Fjs%2Fapp-55bb2aca73.js%3A4%3A30075)
at app-55bb2aca73.js:4
...
Here is my gulpfile.js (use Laravels elexir plugin):
mix.scripts([
/*libs*/
'../../../node_modules/jquery/dist/jquery.slim.min.js',
'../../../node_modules/bootstrap/dist/js/bootstrap.min.js',
'../../../node_modules/angular/angular.min.js',
'../../../node_modules/angular-cookies/angular-cookies.min.js',
'../../../node_modules/pickadate/lib/compressed/picker.js',
'../../../node_modules/pickadate/lib/compressed/picker.date.js',
'../../../node_modules/pickadate/lib/compressed/picker.time.js',
'app.js',
'config/*.js',
'angular/controller/*.js'
], 'public/js/app.js');
Here the app.js:
var app = angular.module("app", ['ngCookies'], function ($interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
});
For example here the begin of a controller:
app.controller('someCtrl', function ($scope, $window, $http, $cookies) {
Someone got any idea why this is not working in one file?
When you minify, the controller method names get stripped out. Need to include in this way to have a reference:
app.controller('someCtrl', ['$scope', '$window', '$http', '$cookies'
function ($scope, $window, $http, $cookies) {
// ...
}
]
More here: https://docs.angularjs.org/guide/di
This might be because the system angular uses for injecting dependencies according to the names of the variables passed as parameters. If you are minifying your files into a single one and variables are not keeping the same original name, you should inject the dependencies manually as follow:
var myApp = function ($interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
}
myApp.$inject = ['$interpolateProvider'];
angular.module("app", ['ngCookies'], myApp);
... and in your controller:
app.controller('someCtrl', controlFn);
var controlFn = function ($scope, $window, $http, $cookies) {};
controlFn.$inject = ['$scope', '$window', '$http', '$cookies'];

Angularjs - injecting dependencies into multiple controllers

I'm still quite new to angular, and have been building a simple CRM application. For a single resource (restful API resource) I have 3-4 routes and controllers defined in my angular application. Now, there are a set of services and modules that I repeatedly have to inject into each controller. I understand that each controller will have it's own instance of scope and shared instance of factory/services but is there a way to centrally define dependencies for multiple controllers?
In the example below, $modal, growl, configuration, $scope are injected into all 3 controllers, I'd like to define that only once.
Listings Controller
myApp.controller('VenueListCtrl', ['$scope', '$http', 'configuration', '$modal', 'growl',
function ($scope, $http, configuration, $modal, growl) {
}
]);
Create/New Controller
myApp.controller('VenueCreateCtrl', ['$scope', '$http', '$location', 'configuration',
function ($scope, $http, $location, configuration) {
}
]);
Details Controller
myApp.controller('VenueDetailCtrl', ['$scope', '$routeParams', '$http', '$modal', 'configuration',
function ($scope, $routeParams, $http, $modal, configuration) {
}
]);
Best you can do is: use not-anonymous function declaration of controllers:
var depsToInject = ['$scope', 'growl', 'configuration', '$modal'];
myApp.controller('Ctrl1' , Ctrl1);
Ctrl1.$inject = depsToInject ;
function Ctrl1($scope, growl, configuration, $modal) {
// ...
}
myApp.controller('Ctrl2' , Ctrl2);
Ctrl2.$inject = depsToInject ;
function Ctrl1($scope, growl, configuration, $modal) {
// ...
}
etc. But that does not fully unify declaration and I don't think there is a better way. However you can try from the other side and wrap your dependencies with another dependency, but I don't like this way either.

Getting controller undefined when trying to run jasmine test

I'm just about to write tests for my angularjs-app. However when Im trying to run the test which is very simpel one i get the following error.
Error: [ng:areq] Argument 'MyPageController' is not a function, got undefined
I'll provide code for the setup of my controllers, config etc.
Route
var myPageApp = angular.module('myPageApp', ['ngRoute', 'ngAnimate', 'ngSanitize', 'app.controller', 'app.service', 'app.filter', 'app.config'])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'App_AngularJs/partials/myPage/myPage.htm',
controller: 'MyPageController',
reloadOnSearch: false,
});
}]);
Controller
var myPageApp = angular.module('app.controller', ['oci.treeview', 'ui.bootstrap'])
.controller('MyPageController', ['$scope', '$routeParams', '$location', '$timeout', '$filter', '$modal', 'myPageService',
function ($scope, $routeParams, $location, $timeout, $filter, $modal, myPageService) {
init();
function init() {
$scope.page = { value: $routeParams.page || 1 };
}
}]);
Simpel test
'use strict';
describe('Testing MyPageController', function(){
var scope;
//mock Application to allow us to inject our own dependencies
beforeEach(angular.mock.module('myPageApp'));
//mock the controller for the same reason and include $rootScope and $controller
beforeEach(angular.mock.inject(function($rootScope, $controller){
//create an empty scope
scope = $rootScope.$new();
//declare the controller and inject our empty scope
$controller('MyPageController', { $scope: scope });
}));
// tests start here
it('should map routes to controllers', function () {
module('myPageApp');
inject(function ($route) {
expect($route.routes['/'].controller).toBe('MyPageController');
expect($route.routes['/'].templateUrl).
toEqual('App_AngularJs/partials/myPage/myPage.htm');
});
});
it('should have variable assigned = "1"', function(){
expect(scope.page.value).toBe(1);
});
});
My wildest and best guess is that i need to mock app.controller but how? Everything starts out with myPageApp which holds references to service, controller etc etc..
I think your issue is that routing and the controller are trying to load different modules viz "myPageApp" and "app.controller" and in your test with beforeEach you are trying to load 'myPageApp' module to which router is associated but not the controller.
So it seems to me that either you use same module for both router and controllers. Or try loading both modules in the test. Still I believe associating the router and controller with same module makes more sense.
An small example as below. Extract the application module in common js file (may be call it app.js)
var myApp = angular.module(
'myApp');
Now define router as
myApp.config(function ($routeProvider) {
$routeProvider
.when('/testUrl', {
templateUrl: '/myApp/views/test-view',
controller: 'TestViewController'
})
Similary define controller as
myApp.controller('TestViewController',[your dependencies goes here])
And now in your tests
beforeEach(module('myApp'));
This will work for sure. Hope it helps.

Using factory within controller in angularjs

I have simple module with controller and factory. I want to use factory within my controller.
So I should add the name of factory within my function() of controller. Adding this, so my controller doesnt work anymore (blank page, no errors)
var app = angular.module('main', ['ngAnimate'])
app.factory('Socket', function($scope) { ... });
My controller works if:
app.controller('DemoCtrl', function($scope, $http, $filter, ngTableParams, $timeout) {...});
My controller does not work if:
app.controller('DemoCtrl', function($scope, $http, $filter, ngTableParams, $timeout, Socket) {...});
Can anyone help me on this?
You can't insert $scope into a service in angular, because it has no meaning in the context of services. $scope is for controllers only, so remove the $scope dependency from your service:
app.factory('Socket', function() { ... });

How do I use an injected angular module's service in my app?

I'm venturing into injecting different angular modules into my app. One module I created contains a service that I would like to inject into a controller. Does anyone have a good explanation of how to do this?
My app.js:
angular.module('myApp', ['ngRoute', 'myModule']);
myModule which contains a service I want to inject:
angular.module('myModule')
.factory('coolService', ['$rootScope', function ($rootScope) {
return {
// API calls
}]);
An example of how to correctly inject 'coolService' into this controller would answer my question nicely:
angular.module('myApp')
.controller('myController', ['$scope', function ($scope) {
...
}]);
angular.module('myApp')
.controller('myController', ['$scope', 'coolService', function ($scope, coolService) {
coolService.do...
}]);
thats all...

Resources