101

Simple question: How can I set a scope value in html, to be read by my controller?

var app = angular.module('app', []);

app.controller('MyController', function($scope) {
  console.log($scope.myVar);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app'>
  <div ng-controller="MyController" app-myVar="test">
    {{myVar}}
  </div>
</div>

JSFiddle: http://jsfiddle.net/ncapito/YdQcX/

Michael
  • 8,362
  • 6
  • 61
  • 88
Nix
  • 57,072
  • 29
  • 149
  • 198
  • You may be better off creating a directive to handle this. A directive would encapsulate: the parameter(s), a controller specific to this directive, and a template for the 'myMap' markup. – Ian Mercer May 28 '13 at 16:53
  • Thats actually what I did... just having some issues with accessing $scope.myVar in the directive controller. Why do I have to use a watch in the controller to access the scope variables? – Nix May 28 '13 at 17:02
  • 1
    Maybe you could post your directive? Take a look at "Understanding transclusion and scopes" here http://docs.angularjs.org/guide/directive You probably need scope: { myVar : '=' } and you would say `my-var="foo"` when you call it. Note use of hyphen vs. camelCase. Note: `foo` here is *evaluated*, if you don't want that use '@' in the scope definition to access the value of the attribute. – Ian Mercer May 28 '13 at 19:17
  • 1
    @Nix Can you explain why the value needs to be initialized in the view, rather than in your controller? I assume you already know that's not the conventional way of initializing values (otherwise you wouldn't be asking), and others will be able to give you better answers if they understand your use case better. – Sean the Bean Mar 14 '16 at 22:49
  • 1
    @SeantheBean i was young and foolish... ;) i have no clue why i needed to do it. I was probably trying to hack around something. – Nix Mar 15 '16 at 13:54

9 Answers9

142

ng-init does not work when you are assigning variables inside loop. Use {{myVariable=whatever;""}}

The trailing "" stops the Angular expression being evaluated to any text.

Then you can simply call {{myVariable}} to output your variable value.

I found this very useful when iterating multiple nested arrays and I wanted to keep my current iteration info in one variable instead of querying it multiple times.

Zanon
  • 29,231
  • 20
  • 113
  • 126
Glogo
  • 2,694
  • 2
  • 23
  • 23
  • 2
    Although this works, it seems hacky. That is, it's generally good practice to use `{{}}` only for outputting a single variable, not for assigning variables. I'd say http://stackoverflow.com/a/16799763/814160 is more correct (less JS code in the view). – Sean the Bean Mar 14 '16 at 22:42
  • 1
    +1 for @SeantheBean - I have tested this. There seems to be issues with child controllers and the scope of assigning the variable in the markup. The directive works for my purposes and appears to be a solid solution. – Paul Carlton Mar 29 '16 at 23:33
  • 2
    This doesn't seem to work in angular2/4 - Bindings cannot contain assignments – Demodave Apr 13 '18 at 13:18
  • 1
    @Demodave you should instead set all your controller variables in Typescript code, and use the template only to connect Typescript to HTML. The template should not be assigning variables. – boxmein Jul 04 '18 at 12:35
84

ngInit can help to initialize variables.

<div ng-app='app'>
    <div ng-controller="MyController" ng-init="myVar='test'">
        {{myVar}}
    </div>
</div>

jsfiddle example

Mark Coleman
  • 40,542
  • 9
  • 81
  • 101
  • 3
    It should be noted they don't recommend this solution for real apps (but don't really suggest an alternative): http://docs.angularjs.org/guide/dev_guide.mvc.understanding_model – Mike Robinson Jun 24 '13 at 16:07
  • This worked for me, however, at first the variable was still undefined in the controller. I made a little interval loop: var interval = setInterval(function() { if ($scope.whatever) { // dostuff clearInterval(interval); } }, 10); – roelleor Jun 26 '15 at 15:31
19

Create a directive called myVar with

scope : { myVar: '@' }

and call it like this:

<div name="my_map" my-var="Richmond,VA">

Note in particular the camel case reference in the directive to the hyphenated tag name.

For more information see "Understanding Transclusion and Scopes" here:- http://docs.angularjs.org/guide/directive

Here's a Fiddle that shows how you can copy values from attributes to scope variables in various different ways within a directive.

Ian Mercer
  • 38,490
  • 8
  • 97
  • 133
  • I want to be able to do multiple ones `var-nick='my' var-nick2='test'`. Unless you can think of a way to implement it with directives I am just going to use `ng-init` – Nix Jun 24 '13 at 16:04
  • You can include multiple attributes in the scope, all you need is for one of them to be the name of the directive that you want to execute (or include that directive name too in the html). `scope: {varNick: '@', varNick2: '@'}` – Ian Mercer Jun 24 '13 at 18:41
  • But its not scalable? I would have to define a directive per variable ? – Nix Jun 24 '13 at 19:02
  • No, you don't need a directive per variable. Take a look at the fiddle I added to the answer. – Ian Mercer Jun 25 '13 at 01:42
  • Sorry I miss read, your example is perfect, my only change was scope{'@': '@"}. – Nix Jun 25 '13 at 12:42
  • really? did it work? i'm kind of having same issue! not solved by following solution :( – genuinefafa Jun 30 '14 at 18:04
  • Fiddle now fixed to work with 1.2.x, thanks @genuinefafa – Ian Mercer Jul 01 '14 at 00:17
  • @IanMercer What is the catch? I cannot follow why is it working now. :$ – genuinefafa Jul 01 '14 at 02:14
  • I moved the HTML into a template: field instead of nesting it in the div directly. Still trying to figure out why that matters between 1.1 and 1.2. – Ian Mercer Jul 01 '14 at 06:38
  • In that case you are cheating @IanMercer! :) I just want to set an scope variable on the markup, to simplify code, but there is no way, isnt it? :( – genuinefafa Jul 01 '14 at 13:43
10

You can set values from html like this. I don't think there is a direct solution from angular yet.

 <div style="visibility: hidden;">{{activeTitle='home'}}</div>
ibsenv
  • 619
  • 1
  • 5
  • 18
3

You can use ng-init as shown below

<div class="TotalForm">
  <label>B/W Print Total</label>
  <div ng-init="{{BWCount=(oMachineAccounts|sumByKey:'BWCOUNT')}}">{{BWCount}}</div>
</div>
<div class="TotalForm">
  <label>Color Print Total</label>
  <div ng-init="{{ColorCount=(oMachineAccounts|sumByKey:'COLORCOUNT')}}">{{ColorCount}}</div>
</div>

and then use the local scope variable in other sections:

<div>Total: BW: {{BWCount}}</div>
<div>Total: COLOR: {{ColorCount}}</div>
Nix
  • 57,072
  • 29
  • 149
  • 198
Mahesh
  • 3,727
  • 1
  • 39
  • 49
  • I like this approach; seems less hacky. One clarification though, ng-init doesn't need the curly braces. – mklbtz Mar 22 '18 at 14:47
1
$scope.$watch('myVar', function (newValue, oldValue) {
        if (typeof (newValue) !== 'undefined') {
            $scope.someothervar= newValue;
//or get some data
            getData();
        }


    }, true);

Variable initializes after controller so you need to watch over it and when it't initialized the use it.

1

If you not in a loop, you can use ng-init else you can use

{{var=foo;""}}

the "" alows not display your var

0

I like the answer but I think it would be better that you create a global scope function that will allow you to set the scope variable needed.

So in the globalController create

$scope.setScopeVariable = function(variable, value){
    $scope[variable] = value;
}

and then in your html file call it

{{setScopeVariable('myVar', 'whatever')}}

This will then allow you to use $scope.myVar in your respective controller

0

You can use the ng-value directive in a hidden field as below :-

<input type="hidden" ng-value="myScopeVar = someValue"/>

This will set the value of the scope variable (myScopeVar) to "someValue"

Golden Griffin
  • 451
  • 1
  • 5
  • 9