90

Hi there I was watching a couple of the angular.js videos and saw that the value() method was used to set a kind of module-wide constant. for example, one can set the Angular-UI library's config like so: (coffeescript)

angular.module('app',[])
.value "ui.config", 
  tinymce:
    theme: 'simple'
    width: '500'
    height: '300'

And my app is currently looking like this:

window.app = angular.module("app", [ 'ui'])

.config(["$routeProvider", ($routeProvider) ->
  $routeProvider
  .when "/users",
    templateUrl: "assets/templates/users/index.html"
    controller: IndexUsersCtrl

  .otherwise redirectTo: "/users"

])

.value 'csrf', $('meta[name="csrf-token"]').attr('content') #<---- attention here

IndexUsersCtrl = ($scope) ->
  $scope.users = gon.rabl
  console.log "I want to log the csrf value here" #<---- then attention
IndexUsersCtrl.$inject = ['$scope']

But I can't seem to get that value by tapping into the 'app' variable which is corresponding to the app module.

I read up here on ST and over on angularjs's google group that one way to share common code btwn controllers is through a service, will this concept apply here, too?

Thanks!

Vasyl Boroviak
  • 5,959
  • 5
  • 51
  • 70
Nik So
  • 16,683
  • 21
  • 74
  • 108
  • 3
    In case you're not aware, the $http service has some CSRF capabilities. See section "Cross Site Request Forgery (XSRF) Protection" here: http://docs.angularjs.org/api/ng.$http – Mark Rajcok Oct 22 '12 at 22:00

3 Answers3

150

Module.value(key, value) is used to inject an editable value, Module.constant(key, value) is used to inject a constant value

The difference between the two isn't so much that you "can't edit a constant", it's more that you can't intercept a constant with $provide and inject something else.

// define a value
app.value('myThing', 'weee');

// define a constant
app.constant('myConst', 'blah');

// use it in a service
app.factory('myService', ['myThing', 'myConst', function(myThing, myConst){
   return {
       whatsMyThing: function() { 
          return myThing; //weee
       },
       getMyConst: function () {
          return myConst; //blah
       }
   };
}]);

// use it in a controller
app.controller('someController', ['$scope', 'myThing', 'myConst', 
    function($scope, myThing, myConst) {
        $scope.foo = myThing; //weee
        $scope.bar = myConst; //blah
    });
Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
Ben Lesh
  • 107,825
  • 47
  • 247
  • 232
  • 4
    how does the 'myService' token fit in to the picture? – Dave Edelhart Jan 14 '13 at 17:30
  • 1
    @DaveEdelhart, Sorry I didn't see your question earlier. I just had it in there as an example of a service that used the value. Fortunately, Pavel Hlobil is a good Samaritan and he added some annotation to my code to make that clearer. – Ben Lesh Feb 04 '13 at 17:08
  • Do you know if the value is read-only? I was not able to find __.value()__ in the documentation... – Pavel Nikolov Apr 12 '13 at 12:21
  • 2
    No it's not "read only". If you were to put an object in there, anything could alter that object's properties. This is mostly because it's JavaScript, and not because of any particular design concern on Angular's part. However, I've not seen value used in a way that it's being altered, usually I've just seen it used for injectible "constants". – Ben Lesh Apr 12 '13 at 13:54
  • @blesh, javascript has readonly properties, so i don't think it's a restriction of the language – Eliran Malka Jul 09 '13 at 10:31
  • @EliranMalka JS has readonly properties, only so long as whatever engine is executing that JS honors readonly properties. Many versions of IE do not support readonly properties. I'm not sure about newer versions of IE. – Ben Lesh Jul 09 '13 at 14:30
  • 1
    @blesh there is $provider.constant() for that (which is probably what poster needs). `constant()`s are immutable, `value()`s can be messed with. – deck Sep 06 '13 at 06:56
  • 2
    However constants are NOT immutable. You just can't overwrite them with another injection because $provide won't intercept them for decoration. – Ben Lesh Sep 06 '13 at 14:59
  • @blesh Isn't it the inability to intercept/overwrite/modify the value that defines the constant as immutable? Related thread in the angular mailing list with a jsBin here: https://groups.google.com/forum/#!topic/angular/vhSaHB3CQKY – deck Sep 25 '13 at 14:51
  • 1
    you can still modify anything defined in an angular constant, at least in the context of whatever you inject it into. So it's not really "constant", in the classical sense. [Take this plunk for example](http://plnkr.co/edit/IORLX21iQwT09cT2RetE?p=preview) You can modify it and it carries over from one controller to the next. You can't, however, intercept it with $provide. Which is the only difference between .constant() and .value() – Ben Lesh Sep 25 '13 at 18:34
  • Because JavaScript passes primitive types by value, the controller or service would need to call `app.value('myThing', newValue)` to change `myThing`. However, in my tests this didn't work (`myThing` keeps its value when the controller is invoked again). How can the controller modify `myThing`? – Dan Dascalescu Oct 26 '14 at 02:06
  • @DanDascalescu if you want to be able to *alter* any primitive value passed to *any function*, regardless of it being in Angular or not, you'll have to pass it as part of a reference type like an Array or Object. – Ben Lesh Nov 04 '14 at 05:19
  • 2
    I know this is an old answer, but "Module.value(key, value) is used to inject an editable value, Module.constant(key, value) is used to inject a constant value" doesn't tally with ng in its latest incarnation (1.3.4). The difference between module.value() and module.constant() is that: a constant() is available earlier in your app's lifecycle (during config and run); value() is only available during run. Whether they are mutable, and where changed values are visible, depends on their value's structure (primitive or not). https://docs.angularjs.org/guide/providers#constant-recipe – lukkea Nov 20 '14 at 12:31
  • How will you decorate your value? – Gaurav Jan 22 '15 at 18:07
  • @lukkea Could you or anybody give an example where a constant can be changed? According a more [recent answer](http://stackoverflow.com/questions/30327651/angularjs-constants-vs-values), a constant should be never changed. Can be, though? – builder Mar 11 '16 at 02:33
  • @builder generally a "constant" is regarded as (and is) immutable, but when dealing with objects this is nuanced. If you have a constant that is an object structure, for example: `app.constant('constantName', { aProp: aValue });` `aValue` is mutable and can therefore be changed. hth. – lukkea Mar 11 '16 at 11:22
4

I recently wanted to use this feature with Karma inside a test. As Dan Doyon points out the key is that you would inject a value just like a controller, service, etc. You can set .value to many different types - strings, arrays of objects, etc. For example:

myvalues.js a file containing value - make sure it is including in your karma conf file

var myConstantsModule = angular.module('test.models', []);
myConstantModule.value('dataitem', 'thedata');
// or something like this if needed
myConstantModule.value('theitems', [                                                                                                                                                                                                             
  {name: 'Item 1'},                                                                                                                                                                                                                         
  {name: 'Item 2'},                                                                                                                                                                                                                         
  {name: 'Item 3'}
]);                                                                                                                                                                                                                         

]);

test/spec/mytest.js - maybe this is a Jasmine spec file loaded by Karma

describe('my model', function() {
    var theValue;
    var theArray;
    beforeEach(module('test.models'));
    beforeEach(inject(function(dataitem,theitems) {
      // note that dataitem is just available
      // after calling module('test.models')
      theValue = dataitem;
      theArray = theitems;
    });
    it('should do something',function() {
      // now you can use the value in your tests as needed
      console.log("The value is " + theValue);
      console.log("The array is " + theArray);
    });
});
SnapShot
  • 5,464
  • 5
  • 42
  • 40
2

You need to reference csrf in your controller IndexUsersCtrl = ( $scope, csrf )

IndexUsersCtrl.$inject = [ '$scope', 'csrf' ]
kaiser
  • 21,817
  • 17
  • 90
  • 110
Dan Doyon
  • 6,710
  • 2
  • 31
  • 40