AngularJS : Differences among = & @ in directive scope?


Creating an isolate scope inside a directive lets us map the outer scope to the inner scope. We have seen six different ways to map to attrbutes:

  1. =attr
  2. &attr
  3. @attr
  4. =
  5. &
  6. @

What do each of these scope mapping options do?

Problem courtesy of: Shaun Luttin


This can be confusing but hopefully a simple example will clarify it. First, let's separate model bindings from behaviors.

Here is a fiddle that should help tie things together:

And explained ... if your directive looks like this:

<my-directive target="foo"/> 

Then you have these possibilities for scope:

{ target : '=' } 

This will bind (directive) to $ (outer scope). This is because = is for two-way binding and when you don't specify anything, it automatically matches the name on the inner scope to the name of the attribute on the directive. Changes to will update $

{ bar : '=target' } 

This will bind to $ This is because again we specify two-way binding, but tell the directive that what is in the attribute "target" should appear on the inner scope as "bar". Changes to will update $

{ target : '@' } 

This will set to "foo" because @ means "take it literally." Changes to won't propagate outside of your directive.

{ bar : '@target' } 

This will set to "foo" because @ takes it's value from the target attribute. Changes to won't propagate outside of your directive.

Now let's talk behaviors. Let's assume your outer scope has this:

$ = function(parm1, parm2) { console.log(parm1 + ": " + parm2); } 

There are several ways you can access this. If your HTML is:

<my-directive target='foo'>


{ target : '=' } 

Will allow you to call,2) from your directive.

Same thing,

{ bar : '=target' }

Allows you to call,2) from your directive.

The more common way is to establish this as a behavior. Technically, ampersand evaluates an expression in the context of the parent. That's important. So I could have:

<my-directive target="a+b" />

And if the parent scope has $scope.a = 1 and $scope.b = 2, then on my directive:

{ target: '&' } 

I can call and the result will be 3. This is important - the binding is exposed as a function to the inner scope but the directive can bind to an expression.

A more common way to do this is:

<my-directive target="foo(val1,val2)"> 

Then you can use:

{ target: '&' }

And call from the directive:{val1: 1, val2: 2}); 

This takes the object you passed, maps the properties to parameters in the evaluated expression and then calls the behavior, this case calling $,2);

You could also do this:

<my-directive target="foo(1, val)"/>

This locks in the first parameter to the literal 1, and from the directive:

{ bar: '&target' }


Which would call $,5);

Solution courtesy of: Jeremy Likness



  1. @attr binds to a matching DOM attribute's evaluated string value.
  2. =attr binds to a matching DOM attribute's scope property.
  3. &attr binds to a matching DOM attribute's scope function.
  4. @
  5. =
  6. &

We use the 4, 5, and 6 if the target DOM attribute's name matches the isolate scope proprty name. Here is a working fiddle of the following example.


<div ng-app='isolate'>
     <h3>Outer Scope</h3>

    <input type="text" ng-model="myModel" />
    <p>msg: {{ msg }}</p>
     <h3>Inner Scope</h3>

    <div id="inner">
        <div my-directive at="{{ myModel }}" equals="myModel" ampersand="msg=msg+'click'"></div>


angular.module('isolate', [])
    .directive('myDirective', function () {
    return {
            '<label>@attr</label><input value="{{ myAt }}" />' +
            '<label>@</label><input value="{{ at }}" />' +
            '<label>=attr</label><input ng-model="myEquals" />' +
            '<label>=</label><input ng-model="equals" />' +
            '<label>&attr</label><input type="button" ng-click="myAmpersand()" value="Btn" />' +
            '<label>&</label><input type="button" ng-click="ampersand()" value="Btn" />',
        scope: {
            myAt: '@at',
            myEquals: '=equals',
            myAmpersand: '&ampersand',
            at: '@',
            equals: '=',
            ampersand: '&'
Discussion courtesy of: Shaun Luttin

This recipe can be found in it's original form on Stack Over Flow.