Tuesday 28 January 2014

Angular configuration - default http headers

Help prevent CSRF attacks by setting the X-Requested-By / X-Posted-By header

angular.module('myApp')
    .config(function($httpProvider) {
        $httpProvider.defaults.headers.common['X-Requested-By'] = 'myApp';
    });

angular.module('myApp')
    .config(function($httpProvider) {
        $httpProvider.defaults.headers.post['X-Posted-By'] = 'myApp';
    });

angular.module('myApp')
    .config(function($httpProvider) {
        $httpProvider.defaults.headers.put['X-Posted-By'] = 'myApp';
    });

Change the default headers at runtime:

$http.defaults.common['X-Auth'] = "foobar";

Security.StackExchange discussion

Monday 27 January 2014

Angular directives - require

If we want to expose an API to other directives, we should require a controller on the directive.

We can bind a controller to the directive with require. Multiple controllers can be required by using an array of strings.

app.directive('foo', function() {
  return {
    require: 'bar',
  }
});

Link function

When a controller is required, it will be passed as the 4th argument to the link function:

app.directive('foo', function() {
  return {
    require: 'bar',
    link: function (scope, element, attrs, bar) {
    }
  }
});

When multiple controllers are required, they will be passed as an array to the link function:

app.directive('foo', function() {
  return {
    require: ['bar, baz'],
    link: function (scope, element, attrs, controllers) {
      var bar = controllers[0];
      var baz = controllers[1];
    }
  }
});

Controller location

We can control where the controller can be found by prefixing the controller name as follows:

no prefix

The required controller must be specified on the directive itself. An exception is thrown if no controller is found.

?

Make the controller optional - if it is not found in the directive provided, null is passed as the 4th argument to
the link function.

ˆ

Walk up the parent chain until the controller is found



Combine the previous two options - walk up the parent chain until the controller is found, and pass null if none is found


Wednesday 22 January 2014

Angular directives - isolate scope

If you don't want a directive to use its parent's scope, create isolate scope:

app.directive("widget", function() {
    return {
        scope : {},    // creates isolate scope
        ...
}

When using isolate scope, obtain access to the parent scope by binding some members:

app.directive("widget", function() {
    return {
        scope : {
            foo: '@' // binds to parent's $scope.foo
        },
        ...
}

3 bindings to parent scope exist:

    '@': 1-way, by value, as a string (updates in the directive are not propagated to the parent scope)
    '=': 2-way, by reference (updates in the directive will update the parent scope)
    '&': expression (the expression is executed in the context of the parent scope)

1-way binding:

app.directive("widget", function() {
    return {
        restrict: 'E', // can only be used as an element
        scope: {
            foo: '@'   // imports $scope.foo by value
        },
        link: function(scope, element, attrs) {
            // do something with attrs.foo
        }


<widget foo="blah"></widget>

In the directive's link function, attrs.foo === "blah".

Model expressions can be parsed too:

<widget foo="{{ model }}"></widget>

In the directive's link function, attrs.foo is a string containing the value in $scope.model.

2-way binding:

app.directive("widget", function() {
    return {
        restrict: 'E', // can only be used as an element
        scope: {
            foo: '='   // imports $scope.foo by reference
        },
        link: function(scope, element, attrs) {
            // do something with attrs.foo
        }


<widget foo="bar"></widget>

In the directive's link function, attrs.foo === $scope.bar. Updating attrs.foo will result in $scope.bar being updated too.

expression binding:

app.directive("widget", function() {
    return {
        restrict: 'E', // can only be used as an element
        scope: {
            foo: '&'   // foo() executed as expression on $scope
        },
        link: function(scope, element, attrs) {
            // attrs.foo() will execute the expression
        }


<widget foo="bar()"></widget>

In the directive's link function, attrs.foo() will execute $scope.bar()

pass parameters to expression:

Special syntax is required to pass parameters to the expression.

In the directive, foo({p1: val}) will pass val to expression foo, which is function bar(p1) on $scope