Use underscore inside Angular controllers - javascript

How do I use underscore library inside angularjs controllers?
On this post: AngularJS limitTo by last 2 records
somebody suggested to assign an _ variable to the rootScope so that the library will be available to all the scopes within the app.
But I'm not clear where to do it. I mean should it go on the app module declaration? i.e:
var myapp = angular.module('offersApp', [])
.config(['$rootScope', function($rootScope) { }
But then where do I load underscore lib? I just have on my index page the ng-app directive and script reference to both the angular-js and underscore libs?
index.html:
<head>
</head>
<body ng-app="offersApp">
...
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="scripts/vendor/angular.js"></script>
<script src="scripts/vendor/underscore.js"></script>
...
How do I achieve this?

When you include Underscore, it attaches itself to the window object, and so is available globally.
So you can use it from Angular code as-is.
You can also wrap it up in a service or a factory, if you'd like it to be injected:
var underscore = angular.module('underscore', []);
underscore.factory('_', ['$window', function($window) {
return $window._; // assumes underscore has already been loaded on the page
}]);
And then you can ask for the _ in your app's module:
// Declare it as a dependency of your module
var app = angular.module('app', ['underscore']);
// And then inject it where you need it
app.controller('Ctrl', function($scope, _) {
// do stuff
});

I have implemented #satchmorun's suggestion here:
https://github.com/andresesfm/angular-underscore-module
To use it:
Make sure you have included underscore.js in your project
<script src="bower_components/underscore/underscore.js">
Get it:
bower install angular-underscore-module
Add angular-underscore-module.js to your main file (index.html)
<script src="bower_components/angular-underscore-module/angular-underscore-module.js"></script>
Add the module as a dependency in your App definition
var myapp = angular.module('MyApp', ['underscore'])
To use, add as an injected dependency to your Controller/Service and it is ready to use
angular.module('MyApp').controller('MyCtrl', function ($scope, _) {
...
//Use underscore
_.each(...);
...

I use this:
var myapp = angular.module('myApp', [])
// allow DI for use in controllers, unit tests
.constant('_', window._)
// use in views, ng-repeat="x in _.range(3)"
.run(function ($rootScope) {
$rootScope._ = window._;
});
See https://github.com/angular/angular.js/wiki/Understanding-Dependency-Injection about halfway for some more info on run.

You can also take a look at this module for angular
https://github.com/floydsoft/angular-underscore

If you don't mind using lodash try out https://github.com/rockabox/ng-lodash it wraps lodash completely so it is the only dependency and you don't need to load any other script files such as lodash.
Lodash is completely off of the window scope and no "hoping" that it's been loaded prior to your module.

you can use this module -> https://github.com/jiahut/ng.lodash
this is for lodash so does underscore

Related

angular module injection error in when running my app

I just started with Angular and I'm little bit confused with this error.
I don't know exactly what I've done wrong, but my console is showing this error:
angular.js:38 Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.5.8/$injector/modulerr?p0=app&p1=Error%3A%20%…(http%3A%2F%2Flocalhost%3A8080%2Flib%2Fangular%2Fangular.min.js%3A21%3A179)(…)
my html:
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<link rel="stylesheet" href="css/app.min.css">
<script src="lib/angular/angular.min.js"></script>
<script src="lib/angular-route/angular-route.min.js"></script>
<script src="lib/angular-resource/angular-resource.min.js"></script>
<script src="js/app.js"></script>
<script src="js/controller.js"></script>
</head>
<body>
test
</body>
</html>
and my app.js:
(function() {
'use strict';
angular.module('app', [
'ngRoute',
'ngResource',
'mainController'
])
.config(['$routeProvider', function() {
routeProvider.when("/", {templateUrl: 'www/index.html', controller: 'mainController'})
}])
.controller('mainController', function($scope){
alert();
})
})();
what is wrong ?
The mainController is not a module but a controller inside your app module. So injecting mainController does not make sense here. Remove the mainController injection from your modules dependencies array.
The other dependencies, ngRoute and ngResources are modules which your module is depending upon - for eg, $routeProvider is from the ngRoute module, so in order to get routeProvider, you need to inject the ngRoute module as dependency.
You don't have to inject controller as a dependency to the module
Change,
angular.module('app', ['ngRoute','ngResource','mainController'])
To
angular.module('app', ['ngRoute','ngResource'])
DEMO
First and foremost, do not inject the controller as a dependency. Remember: you are registering it after you create the module, and adding it to that model. Thus, it would make no sense to inject it at the time of creating the module. It doesn't exist yet. Makes sense?
Then some stuff to make life easier for you: separate out your app config stuff from your controller registrations. Have an app.js for example doing the code below. Notice I separated the steps, and I also create a config function that I then call in the app.config. This is just a bit more readable in the JavaScript mess we have to deal with.
(function() {
'use strict';
var app = angular.module('app', ['ngResource']);
var config = function(routeProvider){
routeProvider.when("/", {templateUrl: 'www/index.html', controller: 'mainController'});
};
app.config(['$routerProvider'], config);
})
})();
Then have a mainController.js containing the controller code and the registration of it. It'll be more future-proof for when you start adding more controllers and services and so on. Also, don't use $scope, use 'this' instead, you can use that from version 1.5 I think. Only place when you need to use $scope because 'this' doesn't work there is in angular charts, just a heads up ;)
(function ()
{
'use strict';
var mainController = function ($scope,)
{
var vm = this;
vm.variable = "value";
};
angular.module('app').controller('mainController', ['', mainController]);
})();
Btw don't mind the strange indentation of the code snippets, the editor on this page is messing with me a bit ;)

Angular: [$injector:modulerr] Failed to instantiate module

I've been trying to set up basic AngularJS functionality for a project but have been hitting a brick wall when it comes to including angular-route. Both are version 1.4.8. I'm currently using gulp-require to concatenate my JS, here's my main javascript file
// =require ../components/jquery/dist/jquery.min.js
// =require ../components/angular/angular.js
// =require ../components/angular-route/angular-route.js
$(document).ready(function() {
// =require app/app.js
}); // Doc ready is done!
And my app.js file
var app = angular.module('myApp', ['ngRoute']);
app.controller("ctrl", ["$scope", 'ngRoute', function($scope) {
$scope.test = "It works!";
}]);
I've checked and all the files are concatenating properly. The ng-app and ng-controller attributes are on my HTML file. I've tried adding and removing the ngRoute injection and switching the order of the files but to no avail. It's frustrating since I used Angular 1.4.5 in almost the exact same way without these issues popping up but I can't replicate the same here even when going back. But the {{test}} variable in my HTML is still not rendering, and basic operations like {{2 + 3}} aren't either.
EDIT: here is the link to the original error message I'm currently receiving: http://tinyurl.com/zx3k85f
EDIT 2: The parts of my HTML code that's calling the app and the controller:
<html lang="en" ng-app="myApp">
<body ng-controller="ctrl">
</body>
</html>
I'm using nunjucks for HTML dynamic generation, although I've changed the syntax for this so it doesn't conflict with Angular's double curly braces.
You can't inject module as dependency inside controller, you should remove 'ngRoute' from the controller DI inline array.
app.controller("ctrl", ["$scope", , function($scope) {
Update
Basically the real problem is you are loading your angular component script using requirejs(lazily), so while you are having ng-app="myApp" with module name start looking for myApp module, and the module has not loaded therefore it throws an error .
So I'd recommend you to don't use ng-app directive to start angular on page load. Instead you should wait until all the scripts related to angular loaded, & then to bootstrap angular app lazily using angular.bootstrap method.
Code
$(document).ready(function() {
requirejs(["app/app.js"], function(util) {
angular.bootstrap(document, ['myApp']);
});
});
ngRoute is a provider that needs to be configured in the module config section before being used. Using it within a controller does not make any sense. Here the version that will work:
angular.module('myApp', ['ngRoute']);
angular.module('myApp').controller("ctrl", ["$scope",function($scope) {
$scope.test = "It works!";
}]);
Moreover, you need to call your module using directive ng-app=myapp in the html element where you plan to render your app.

AngularJS Controller is not a function error

I'm getting error when adding ng-controller="HeaderController" to a div.
Error: ng:areq
Bad Argument
Argument 'HeaderController' is not a function, got undefined
my HTML looks like that:
<div ng-app="myApp">
<div ng-controller="HeaderController">
</div>
<div ng-controller="PostController">
</div>
</div>
Also I include following files:
MyApp.js
var myApp = angular.module('myApp', ['postServices', 'angularFileUpload', 'ngSanitize', 'ui.date', 'bootstrapLightbox', 'profileServices']);
HeaderController.js
myApp.controller('HeaderController', ['$scope', 'PostServices', '$http', function($scope, PostServices, $http) {
$scope.getBookmarksCount = function() {
PostServices.getBookmarksCount().then(function(response) {
if (response.data.status == 'success') {
$scope.bookmarksCount = response.data.bookmarksCount;
} else {
$scope.errorMessage = response.data.message;
}
})
};
}]);
PostController.js beggining of this file looks like:
myApp.controller('PostController', ['$scope', 'PostServices', '$http', 'FileUploader', 'Lightbox',function($scope, PostServices, $http, FileUploader, Lightbox) {
PostService.js contains a module named postServices and it contains a service PostServices:
angular.module('postServices', [])
.service('PostServices', ['$http', function($http) {
if I delete ng-controller="HeaderController" everything works fine.
Does anyone knows what could be the problem?
In your module you add the postServices without a capital at the start, while you add it in your headercontroller as PostServices. This might mess with the forming of your headercontroller.
Either one of those could be a typo, but it is very important that you inject the service precisely as it is defined (in your .service or .factory) in the ['PostService', bit. So if the service is called: postService, you should inject it in your controller as: ['postService, function(someNameThatDoesntMatter) if its called PostService, inject it as ['PostService', function(someNameThatDoesntMatter)
As I just shown, how you call it afterwards in the function parameter is up to you.
Update
You could create a module for your controllers to fix this. Make sure to inject your postServices in this module aswell. Then inject the controllers module in your myApp module :-) The benefit of working in a structured way like this, is that you can create a structure of including your JS which you can apply on every project you work on.
I don't know which version of Angular you use , I took 1.4.0 for my plunk example and try just to limit to the code you provide to see if I recreated the error.
I had to deal more with scripts inclusion order. It created error. The right order in order to make it work is
<link rel="stylesheet" href="style.css">
<script src="//code.angularjs.org/1.4.0/angular.js"></script>
<script src="MyApp.js"></script>
<script src="PostController.js"></script>
<script src="PostService.js"></script>
<script src="HeaderController.js"></script>
http://plnkr.co/edit/NhzQFmI1s9r98uAMZwYg
So Main point was to defined PostService.js before HeaderController
It seems likes
you forget include that HeaderController.js file in index.html.
Make sure your HeaderController.js is loaded properly.
Missing some where in gulp/grunt process.

Dependency Injecting an empty module into a controller in Angular

I am trying to dependency inject a module into another—the former is simply an empty module.
angular.module('module1', []);
angular.module('module2', [])
.controller('Module2Ctrl', ['module1', '$scope', function (module1, $scope) {
$scope.expression = 'hello!';
}]);
HTML:
<html ng-app="module2">
<body ng-controller="Module2Ctrl">
<h1>{{expression}}</h1>
</body>
</html>
I'm getting the dreaded Unknown provider: module1Provider <- module1 <- Module2Ctrl message.
What's going on? I believe everything is defined as it should be—though module1 has no definitions, I can't find information anywhere on what would stop this from working.
Plnkr: http://plnkr.co/edit/goMVFRNuPgG6iIpGYI1Y?p=preview
Thanks :-)
You inject providers (such as factories, services, ...), not modules. Remove the module1 injection and it will work. What you're thinking of doing is probably declaring module2 as a module dependency of module1:
angular.module('module1', ['module2']);
and then ng-app="module".
angular.module can not injected inside a controller,Only one angular.module can be injected inside another module.
angular.module('module2', ['module1'])
You should never do that angular. Only angular components are inject-able like service,controller, factory, filter, provider,etc.
For initializing angular on page you could do angular.bootstrap
angular.bootstrap(document,["module2"])

angular force me to make variables on window

I want to follow angularjs recommendation (http://docs.angularjs.org/guide/module):
While the example above is simple, it will not scale to large
applications. Instead we recommend that you break your application to
multiple modules like this:
A service module, for service declaration A directive module, for
directive declaration A filter module, for filter declaration And an
application level module which depends on the above modules, and which
has initialization code.
So I've created services.js file that only contains:
window.myservices = angular.module('services', []);
And then I added a few services where each service file starts with:
window.myservices.factory('service1', function() {
....
});
I made the same for filters.js and directives.js.
In my app.js file I made:
window.App = angular.module('app', ['services', 'filters', 'directives']).
// run \ config \ whatever
How can I do it without making variables on window?
There's no need for globals at all:
// Define your services
angular.module('services', [])
.factory('service1', function(){})
.factory('service2', function(){});
// Define you main app module and specify the dependencies
angular.module('MyApp', ['services']);
As Stewie said, you can use angular.modue('service',[]);
However you only need to do this in the first loaded file, like so:
file1.js
var mod = angular.module('service',['dependancy']);
file2.js
var mod = angular.module('service');
index.html
<script src="/scripts/file1.js"></script>
<script src="/scripts/file2.js"></script>
Another option is to use namespaces...
file1.js
var mod = angular.module('service.part1',[]);
file2.js
var mod = angular.module('service.part2',[]);
main.js
var mod = angular.moduel('service', ['service.part1','service.part2']);
EDIT (plunker):
http://plnkr.co/edit/i75A5CQeSptQjaxvR8qi?p=preview

Categories