AngularJS

Client-side technology, written entirely in JavaScript. It works with the long-established technologies of the web (HTML, CSS, and JavaScript) to make the development of web apps easier and faster than ever before.

It is a framework that is primarily used to build single-page web applications. AngularJS makes it easy to build interactive, modern web applications by increasing the level of abstraction between the developer and common web app development tasks.

AngularJS creates live templates as a view. Individual components of the views are dynamically interpolated live. The ng-app attribute declares that everything inside of it
belongs to this Angular app; that’s how we can nest an Angular app inside of a web app. The only components that will be affected by Angular are the DOM elements that we declare inside of the one with the ng-app attribute.

Views are interpolated when the view is evaluated with one or more variable substitutions; the result is that the variables in our string are replaced with values. For instance, if there is a variable named name and it is equal to ‘Ari’, string interpolation on a view of ‘Hello {{ name }}’ will return ‘Hello Ari’.

Automatic data binding gives us the ability to consider the view to be a projection of the model state. Any time the model is changed in the client-side model, the view reflects these changes without writing any custom code.

One of the major changes coming in AngularJS 2.0 is the death of the controller, and a new emphasis on components. In this context, component is a loose term for a DOM element that has its own view, model, and behaviors. With Angular 1, we can reformulate Hello World as a directive to achieve more of a component-based architecture:

# index.html
<hello-world>
 
# helloWorldTemplate.html
<strong>{{message}}</strong>
 
# helloWorldDirective.js
demoApp.directive('helloWorld', function() {  
  return {
    restrict: 'E',
    templateUrl: 'helloWorldTemplate.html',
    link: function(scope, element, attrs) {
      scope.message = 'Hello World';
    }
  };
});

Directives

A built-in directive is one that ships out of the box with Angular. All built-in directives are prefixed with the ng namespace. In order to avoid namespace collisions, do not prefix the name of your own directives with ng.

The ng-app directive defines an AngularJS application.

Create a very basic custom directive:

<body ng-app="myappApp">
  <my-directive></my-directive>
</body>

When Angular compiles our HTML, it will invoke this directive. Invoking a directive means to run the associated JavaScript that sits behind our directive, which we
define using a directive definition:

angular.module('myappApp', [])
.directive('myDirective', function() {
  return {
    restrict: 'E',
    template: '<a href="http://google.com">Click me to go to Google</a>'
  }
});

By default, Angular nests the HTML provided by our template string inside of our custom HTML tag, , in the generated source code. We can remove our custom element ( ) from the generated DOM completely and output only the link we’re providing to the template option. To do so, set the replace option to true (replace: true). The following are valid formats for declaring the directive we built above:

<my-directive></my-directive>
<div my-directive></div>
<div class="my-directive"></div>
<!-- directive: my-directive -->

In order to allow for Angular to invoke our directive, we’ll need to change the restrict option inside our directive definition. This option tells Angular which declaration format(s) to look for when compiling our HTML. We can specify one or many formats. For example, in the directive we’re building, we can specify that we want our directive to be invoked if it is an element ( E ), an attribute ( A ), a class ( C ), or a comment ( M ).

Regardless of how many ways (restrict: ‘EAC’) we can declare a directive, we’ll stick to using an attribute (the way that is compliant across the most browsers):

<div my-directive></div>

Given that a directive can (and usually should) be invoked as an attribute, we’re inclined to ask about the value passed to that attribute:

<h1 ng-init="greeting = 'Hello World'">
The greeting is: {{ greeting }}
</h1>

Notice that we’ve passed the expression greeting = ‘Hello World’ to the built-in directive ng-init.

<div my-directive="someExpression"></div>
<div my-directive my-url="http://google.com" my-link-text="Click me to go to Google"></div>
 
angular.module('myappApp', [])
.directive('myDirective', function() {
  return {
    restrict: 'A',
    replace: true,
    template: '<a href="{{myUrl}}">{{myLinkText}}</a>'
  };
});

Reload the page and notice that the div where we declared our directive has been replaced by its template; however, the link’s href is empty, and there’s no text inside the brackets. Angular provides the ability to create a new child scope or create an isolate scope. Essentially, that means the directive gets its own $scope object, which we can only use inside other methods of the directive or inside the directive’s template string:

angular.module('myApp', [])
  .directive('myDirective', function() {
    return {
      restrict: 'A',
      replace: true,
      scope: {
        myUrl: '@',     // binding strategy
        myLinkText: '@' // binding strategy
      },
    template: '<a href="{{myUrl}}">' + '{{myLinkText}}</a>'
  }
})

Let’s see what happens if we create a text field and bind the input value to a property on the $scope of our isolate directive. Using the ng-model directive binds the input text to the myUrl attribute on the $scope object.

<input type="text" ng-model="myUrl" />
<div my-directive some-attr="{{ myUrl }}" my-link-text="Click me to go to Google"></div>

Two-way bindings are perhaps the most important feature in Angular. Let’s create a two-way data binding between our isolate $scope and the isolate $scope inside ng-model. We do that by binding our internal $scope.myUrl property with a property named theirUrl on the $scope of the current controller (or $rootScope ) using scope lookup in the DOM. Let’s also add an additional text field so that each side of the binding has its own text field. Having two fields will make it easy to see how scope is being linked via prototypal inheritance in the DOM:

<label>Their URL field:</label>
<input type="text" ng-model="theirUrl">
<div my-directive some-attr="theirUrl" my-link-text="Click me to go to Google"></div>
 
angular.module('myApp', [])
  .directive('myDirective', function() {
    return {
      restrict: 'A',
      replace: true,
      scope: {
        myUrl: '=someAttr', // MODIFIED
        myLinkText: '@'
      },
      template: '\
      <div>\
        <label>My Url Field:</label>\
        <input type="text"\
        ng-model="myUrl" />\
        <a href="{{myUrl}}">{{myLinkText}}</a>\
      </div>\
      '
    }
})

Leave a Reply