Use underscore inside Angular controllers

103,733

Solution 1

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
});

Solution 2

I have implemented @satchmorun's suggestion here: https://github.com/andresesfm/angular-underscore-module

To use it:

  1. Make sure you have included underscore.js in your project

    <script src="bower_components/underscore/underscore.js">
    
  2. Get it:

    bower install angular-underscore-module
    
  3. Add angular-underscore-module.js to your main file (index.html)

    <script src="bower_components/angular-underscore-module/angular-underscore-module.js"></script>
    
  4. Add the module as a dependency in your App definition

    var myapp = angular.module('MyApp', ['underscore'])
    
  5. 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(...);
    ...
    

Solution 3

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.

Solution 4

You can also take a look at this module for angular

https://github.com/floydsoft/angular-underscore

Solution 5

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.

Share:
103,733
Pablo
Author by

Pablo

Updated on October 30, 2020

Comments

  • Pablo
    Pablo over 3 years

    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?

  • Walter Stabosz
    Walter Stabosz about 11 years
    I don't understand why you would inject it when it is already in the global window scope.
  • fess .
    fess . almost 11 years
    Probably for the same reasons you inject anything, instead of putting everything in the global scope. However, since you're a lot less likely to want to substitute out your underscore library during testing than some other more specific dependency it's understandable that it doesn't seem necessary.
  • Shanimal
    Shanimal almost 11 years
    its necessary when you add 'use strict' to your file. Since underscore/lodash isn't defined it will throw ReferenceError: _ is not defined... you have to inject it, or use window._
  • Aditya M P
    Aditya M P almost 11 years
    Ha! I wanted to do the injecting because it's cool, thanks for giving me a real reason, @Shanimal.
  • sunwukung
    sunwukung almost 11 years
    you might also want to inject _ for the sake of testing. How would you go about bringing the underscore dependency into a test suite environment
  • zakdances
    zakdances over 10 years
    Couldn't you also just do var _ = window._; at the top of your controller?
  • holographic-principle
    holographic-principle over 10 years
    @Shanimal that's not true. It works by just accessing _ (as a global) in strict mode as well.
  • Michal Charemza
    Michal Charemza over 10 years
    Angular already provides $window that can be injected into controllers, which is just a reference to the global window object. Then you can access $window._ in the controller, without accessing the global scope directly.
  • Jan Molak
    Jan Molak over 10 years
    I agree with @MichalCharemza, try to avoid using global window object in your service. The above example rewritten to use $window would look more or less like this: angular.module('underscore', []); angular.module('underscore').factory('_', ['$window', function ($window) { return $window._; }]);
  • chovy
    chovy almost 10 years
    how do you load this thing in a controller?
  • chovy
    chovy almost 10 years
    Does not appear to work. I get an undefined error: Uncaught ReferenceError: _ is not defined
  • unify
    unify almost 10 years
    I added the clarification: you need to include underscore.js. This connector only helps you to use it in a service. See @satchmorun's answer
  • Nate
    Nate over 9 years
    this looks good but do you have an example? I need to change all uppercase to upper on first character only using _.capitalize()
  • wires
    wires over 9 years
    I think this should work <p>{{ _.capitalize('lalala') }}</p> ?
  • Mark Amery
    Mark Amery over 9 years
    @Shanimal despite its many upvotes, your comment is nonsense; "use strict"; prevents globals from being implicitly declared, by assigning to a name that hasn't been declared with var or otherwise created in a visible scope. It does not require you to access existing, declared globals as window properties. You can simply access them as variables, which they are. window itself is a global variable, for goodness' sake; if what you were saying were true, all globals would be strictly inaccessible by any means whatsoever.
  • wires
    wires over 9 years
    @LVarayut I don't know, why not try it? (I have since moved to ReactJS)
  • Michał Miszczyszyn
    Michał Miszczyszyn about 9 years
    You should use $window instead of window.
  • Tim Hong
    Tim Hong almost 9 years
    Please use service instead. Avoid adding stuff to your $rootScope will help you to have better performance.
  • Luke
    Luke almost 9 years
    I would think that underscore is more of a service than a factory (based on this stackoverflow.com/a/21900284/1766230) Why use factory instead of service?
  • Trevor
    Trevor almost 8 years
    I always worry about modules that haven't been updated for years
  • Paul Preibisch
    Paul Preibisch over 7 years
    can you please provide usage instructions
  • Olivvv
    Olivvv about 7 years
    Not sure what I did wrong but I could not get the "use in views" part to work. But passing the service to the controller and then to the tpl through $ctrl works.