The jQuery perspective

Basically, jQuery could be a useful gizmo for you to employ and control DOM components. If you merely specialize in DOM components and not CRUD implementation, such as building static websites and not dynamic data-driven web applications, jQuery is the tool for you. For example, to create a dialog box with jQuery, you would first add a standard div element to the HTML code; however, in jQuery, we tend to call $(element).dialog() to convert the div element into a dialog box, as shown in the following code.

Even a designer who examines it will not be able to understand if you have used a comprehensible div element or a dialog box. You have to look into the jQuery for the details:

<div id="divDialogBox">

<script>
$(document).ready(function(){

    $('# divDialogBox').dialog()
})
</script>

On the other hand, in AngularJS, there is an extremely structured view and approach to achieve what you would like to accomplish. It hardly follows a linear method of competing a task, but rather, the exchanges between varied objects and actions are vital as AngularJS is an MVC-based framework. Together, it wants a minimum general design of the finalized application, since coding depends on you and you would like the interactions to be completed.

Compared to AngularJS, jQuery is an assortment of codes and functions (which is, as already mentioned, good for DOM manipulation and fast effective achievement). AngularJS can be a true framework that provides a developer with the ability to create an enterprise web application with several data bindings and exchanges within wonderfully organized routing and management.

The AngularJS approach is to use a directive to extend HTML. So, a directive for a dialog box could look like this:

<dialog-box></dialog-box>

< !- - OR - ->

<div dialog-box></div>

This approach to create HTML components is instinctual and rich. You can simply look at the element to know what it is supposed to be. AngularJS provides the following features that the jQuery library does not have:

  • The MVC design pattern
  • One-way and two-way data binding
  • Templates
  • Validating the form
  • Dynamic page deep linking
  • Communication with server-side code
  • Components are reusable

Basic behavior

AngularJS's custom directives normally yield a verbatim object that is answerable for defining the properties required by the directive, such as templates, a controller (if any is used), or HTML manipulated code. The following table gives you a glance of a few key properties:

Property

Description

restrict

This restricts where a directive will be used. For example, an element, a CSS class, attribute, or comment.

Template

This outputs the content of the directive. It can be in the form of HTML, data binding, or other directives.

templateUrl

This is the path to the template, which is used by the directive.

Controller

This defines the controller that will be used within the directive template.

Scope

This is used to create a new child scope or to segregate a scope.

Link

This is the function which is used for the DOM.

The restrict property

The type of restriction defines how the directive is initiated. The directive has the following restrict types:

  • A: This matches the attribute name
  • E: This matches the element name
  • C: This matches the class name

The preceding restrictions can also be used in combination, for example, AEC. Let's modify the preceding code and use the AEC restriction. The following code shows the custom directive using the restrict property to restrict the directive:

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

<!-- CONTROLLER -->
app.controller("ctrlRestrictDirective", function ($scope) {

});

<!-- DIRECTIVE -->
app.directive('myRestrictDirective', function () {

return {

restrict: 'AEC', //<!—- A=attributes, E=element, and C= class -- >
template: '<p>This is a restrict directive</p>'

}

});

To invoke the preceding directive code, we can use an HTML element, attribute, or a CSS class, shown as follows:

<div ng-app="myApp" ng-controller="ctrlRestrictDirective">

<p my-restrict-directive></p><!-- Attribute -->

<my-restrict-directive></my-restrict-directive><!-- ELEMENT -->

<p class="my-restrict-directive"></p><!-- CLASS -->

</div>

The template and templateUrl properties

A simple way to create a custom directive is to use a template, as shown in the preceding example. The template property of the directive will generate HTML; put that HTML inside the template attribute of the directive attribute. In the preceding example, we added a <div> HTML element into the directive's template property. However, in some instances, if the template is very big, it will become very hard to write and maintain HTML inside a template as a string. In this case, we can use the templateUrl property of the directive. We will have to create a separate HTML page and load it using the templateUrl property. The templateUrl property will load the page from the URL set in the directive. Using the separate HTML page and the templateUrl directive property is useful when you want to create more specific directives.

Note

Best practice: Create separate HTML pages and load them by using the templateUrl directive property, unless the template is very small.

The scope property

Directives get their parent scope by default. Sometimes, we do not want its parent scope. If a directive exposes its parent scope, it can modify the properties of that scope. However, sometimes a few properties and functions are added to the scope that we want to use only for this directive and do not want to expose to the parent scope. If we are not exposing the directive properties and functions to the parent scope, it means that we are polluting it.

In order to expose the directives and functions to the parent scope, we can use the following two options:

  • Child scope: This scope will inherit the parent's scope.
  • Isolated scope: This is a new scope that will not inherit from the parent's scope.

While creating a new custom directive, the scope property of the directive can be configured with either the child scope or the isolated scope. The following code example configures the directive's scope property with the child scope:

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

<!-- CONTROLLER -->
app.controller("ctrlDirectiveScope", function ($scope) {

        $scope.controllergreeting = 'Welcome to Mastering AngularJS';
});

<!-- DIRECTIVE -->
app.directive('myDirectiveScope', function () {
return {
restrict: 'AEC', //<!—- A=attributes, E=element, and C= class -- >
scope:true,
template: '{{controllergreeting}}'
           }

});

We will invoke the preceding code in HTML as follows:

<div ng-app="myApp" ng-controller="ctrlDirectiveScope">

<p my-directive-scope></p><!-- Attribute -->

<!- - OR - - >

<my-directive-scope></my-directive-scope><!-- ELEMENT -->

<!- - OR - - >

<p class="my-directive-scope"></p><!-- CLASS -->

</div>

In order to reuse the directive, we rely on the controller, which we will discuss in detail in Chapter 3, AngularJS Scopes, Controllers and Filters. If you want to reuse the directive, but do not want to depend on the parent scope, you must use the isolated scope. The following figure explains the concepts of parent and isolated scopes in the directive:

The scope property

The following code example configures the directive's scope property with the isolated scope:

var app = angular.module('myApp', []);
<!-- CONTROLLER -->
app.controller("ctrlIsolateScope", function ($scope) {
$scope.controllergreeting = 'Welcome to Mastering AngularJS';
  });
<!-- DIRECTIVE -->
app.directive('myIsolateScope', function () {                
return {
restrict: 'AEC', //<!—- A=attributes, E=element, and C= class -- >
scope:{},
template: '{{controllergreeting}}'
}
});

We will invoke the preceding code in HTML, as follows:

<div ng-app="myApp" ng-controller="ctrlIsolateScope">
<p my-isolate-scope></p><!-- Attribute -->
<!- - OR - - >
<my-isolate-scope></my-isolate-scope><!-- ELEMENT -->
<!- - OR - - >
<p class="my-isolate-scope"></p><!-- CLASS -->
</div>

In the preceding code example, we saw that the directive used the isolated scope, which will not inherit from the parent scope. Now, with the directive scope isolated, the parent scope will no longer be accessible. When we invoke the directive in the HTML view, it will show nothing because the value will not be rendered. Now, when the directive is completely cut off from the parent scope, how will we pass data into the directive for data binding? Let's take a look at how we can bind the data when we are using the isolated scope property in the directive.

The @ local scope property

In order to access the string value from outside the directive, the @ local scope property will be used. For example, as you can see in the preceding example, controllerGreeting is defined in the controller, which is accessed through the $scope. In order to access the controllerGreeting property, we will use @.The following code shows how to use the @ local scope property:

var app = angular.module('myApp', []);
<!-- CONTROLLER -->
app.controller("ctrlIsolatePropertyAt", function ($scope) {
     $scope.controllergreeting = 'Welcome to Mastering AngularJS';
});


<!-- DIRECTIVE -->
app.directive('myIsolatePropertyAt', function () {
return {
restrict: 'AEC', //<!—- A=attributes, E=element, and C= class -- >
scope: {
controllergreeting: '@'
}, 

template: '{{controllergreeting}}'
}
});

In the preceding code, the $scope.controllergreeting property of the controller property is bound using the @ local isolated property. The content rendered by the HTML element is as follows:

<div ng-app="myApp" ng-controller="ctrlIsolatePropertyAt">

<!-- Attribute -->
<p my-isolate-property-at controllergreeting="{{controllergreeting}}"></p>
<!-- ELEMENT -->
<my-isolate-property-at controllergreeting="{{controllergreeting}}">
</my-isolate-property-at>
<!-- CLASS -->
<p class="my-isolate-property-at" controllergreeting="{{controllergreeting}}"></p>

</div>

If you want the local directive property name to be different from the property name in the controller, use the following syntax:

var app= angular.module('myApp', []);
<!-- CONTROLLER -->
app.controller("ctrlIsolatePropertyAtWithCustomPropertyName", function ($scope) {
    $scope.controllergreeting = 'Welcome to Mastering AngularJS';
});
<!-- DIRECTIVE -->
app.directive('myIsolatePropertyAtWithCustomPropertyName', function () {
return {
restrict: 'AEC', //<!—- A=attributes, E=element, and C= class -- >
scope: {
controllergreeting: '@Greeting'
}, 
template: '{{controllergreeting}}'
    }
});

It will be rendered in HTML, as follows:

<divng-app="myApp"ng-controller="ctrlIsolatePropertyAtWithCustomPropertyName">
<!-- Attribute -->
<p my-isolate-property-at-with-custom-property-name greeting="{{controllergreeting}}"></p>
<!-- ELEMENT -->
<my-isolate-property-at-with-custom-property-name greeting="{{controllergreeting}}"></my-isolate-property-at-with-custom-property-name>
<!-- CLASS -->
<p class="my-isolate-property-at-with-custom-property-name" greeting="{{controllergreeting}}"></p>

</div>

If the value of the controllergreeting controller property changes, the directive value will change automatically. However, if the directive changes its property name to something else, the outside controllergreeting property will not change. In order to keep the controller and directive property in sync, we have to use the = local scope property.

The = local scope property

The = local scope property is used whenever we need two-way binding between the controller scope (that sets up the initial state of an object as well as adds an additional behavior when needed) and the directive isolated scope. In other words, when we need to sync the controller scope with the directive isolated scope, we use the = character. As in our preceding example, the controller defines the $scope.controllergreeting property, which the $scope.controllergreeting property passes into the directive in a way that creates two-way binding. The directive creates a controllergreeting custom local scope property, as shown in the following code. The = character tells the directive that the property passed should be in two-way binding. If the controller property value changes, the directive local scope property changes automatically and vice versa: var app = angular.module('myApp', []);. The code that follows is an example of how to implement two-way binding using =:

<!-- CONTROLLER -->
app.controller("ctrlIsolatePropertyEqual", function ($scope) {

      $scope.controllergreeting = 'Welcome to Mastering AngularJS';

});

<!-- DIRECTIVE -->
app.directive('myIsolatePropertyEqual', function () {

return {
restrict: 'AEC',
scope: {
controllergreeting: '='
              },
template: '<input type="text" ng-model="controllergreeting" style="width:100%" />'
                                      }
});

We render the HTML elements as follows:

<divng-app="myApp"ng-controller="ctrlIsolatePropertyEqual">

<!-- BINDING WITH CONTROLLER -->
<input type="text" ng-model="controllergreeting" style="width:100%" /><br /><br />


<!-- BINDING WITH DIRECTIVE -->

<!-- ELEMENT -->
<my-isolate-property-equal controllergreeting="controllergreeting"></my-isolate-property-equal>

<!-- Attribute -->
<div my-isolate-property-equal controllergreeting="controllergreeting"></div><br />

<!-- CLASS -->
<div class="my-isolate-property-equal" controllergreeting="controllergreeting"></div>
</div>

As you can see in the preceding code, we have bound the <input> element with the controller property and the <div> element with the directive element. If you change the value of the <div> element, it will change the value of the <input> element automatically and vice versa.

The & local scope property

We have discussed the @ local scope property, which is used to pass the string value of the controller property to the directive property. We also covered the = local scope property for two-way data binding. In this section, we are going to talk about the & local scope property to bind external functions. The & local scope property lets the HTML element, which is invoking the directive, call the controller function using the & local property, as shown in the following code example:

var app = angular.module('myApp', []);
<!-- CONTROLLER -->
app.controller("ctrlIsolatePropertyAnd", function ($scope) {
$scope.showAlertMessage = function () {
alert('This is an alert message from Controller'),
};
});
<!-- DIRECTIVE -->
app.directive('myIsolatePropertyAnd', function () {
return {
restrict: 'AEC',
scope: {
invokecontrollerfunction: '&'
},
template: '<button ng-click="invokecontrollerfunction()">Invoke 
Controller Function</button>'
};
});

We will render the HTML elements, as follows:

<div ng-app="myApp" ng-controller="ctrlIsolatePropertyAnd">
<!-- Attribute -->
<div my-isolate-property-and invokecontrollerfunction="showAlertMessage()"></div><br />
<!-- ELEMENT -->
<my-isolate-property-and invokecontrollerfunction="showAlertMessage()"></my-isolate-property-and><br /><br />

<!-- CLASS -->
<div class="my-isolate-property-and" invokecontrollerfunction="showAlertMessage()"></div>
</div>

In the preceding example, the controller defines the $scope.showAlertMessage function. This controller function needs to be passed to the directive so that we can invoke this function on a button's click. To pass the $scope.showAlertMessage function to the directive in the directive's local scope property, invokecontrollerfunction is created, as shown in preceding code invokecontrollerfunction: '&'.

We talked about three isolated scope properties @, =, and &. The @ isolate property is one-way binding between the parent and directive scope. This property always maps an attribute to an expression. In order to make the @ property work, we need to wrap the attributes value inside {{}}, such as controllergreeting="{{controllergreeting.}}". Since @ creates one-way binding, any changes in the parent scope will change the directive scope, but any changes in the directive scope will not make any changes to the parent scope. The isolate property is very useful when the directive initializes any data from the parent scope.

The = isolate property of a directive creates two-way binding between the directive and parent scope. This property always expects the attribute value to be the model name. Using this property, we can wrap the attribute's values with =, such as controllergreeting="controllergreeting".

Finally, the & isolate property is known as function binding. This property is used to bind the function from the parent scope to the directive scope. This property is very useful when a directive needs to call any function from the parent scope.

Transclusion

We can define transclusion as the insertion of an HTML element into another HTML element by reference at runtime. In the AngularJS framework, transclusion is a feature that will replace the DOM element into the directive temple element at a specific position. When we set transclude:true in the directive definition, it will create a new scope that inherits from the parent scope. Transclusion can be used to isolate the scope so that it contains an arbitrary piece of content and so that it is executed against the parent scope. The following code example shows the use of transclude:

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

<!--**************** TRANSCLUSION OFF *********************-->
<!-- CONTROLLER -->
app.controller("ctrlTransclusionOff", function ($scope) {
});
<!-- DIRECTIVE -->
app.directive('myTransclusionOff', function () {
return {
restrict: "AEC",
template: '<div>This is an element from a directive, which is not replaced with 
DOM element</div>'
    };
});
<!--**************** TRANSCLUSION *********************-->
<!-- CONTROLLER -->
app.controller("ctrlTransclusion", function ($scope) {
});
<!-- DIRECTIVE -->
app.directive('myTransclusion', function () {
return {
restrict: "AEC",
transclude: true,
template: '<div ng-transclude>This is a transcule test</div>'
    };
});

We will call this in HTML, as follows:

<div ng-controller="ctrlTransclusionOff">
<div my-transclusion-off>
<button>Click me!</button>
</div>
</div>
<div ng-controller="ctrlTransclusion">
<p>The DOM element <xmp>"<button>"</xmp> gets replaced with directive element</p>
<div my-transclusion>
<button>Click me!</button>
</div></div>

In the preceding code, the <button> DOM element will be replaced with This is a template element.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset