Communication Between Components Using @Input() in Angular

In Angular 2 a component can share data and information with another component by passing data or events. A component can be used inside another component, thus creating a component hierarchy. The component being used inside another component is known as the child component and the enclosing component is known as the parent component. Components can communicate to each other in various ways, including:

  • Using @Input()
  • Using @Output()
  • Using Services
  • Parent component calling ViewChild
  • Parent interacting with child using a local variable

In this article, we will focus on how a child component can interact with a parent component using the @Input() property. We’ll also look into intercepting the input message and logging changes in the input message.

image

Let us consider the components created in the listing below. We have created a component called AppChildComponent, which will be used inside another component.

We have also created another component called AppComponent. Inside AppComponent, we are using AppChildComponent:

In the above listings, AppComonent is using AppChildComponent, hence AppComponent is the parent component and AppChildComponent is the child component.

Passing data from parent component to child component

Let us start with passing data from the parent component to the child component. This can be done using the input property. @Input decorator or input properties are used to pass data from parent to child component. To do this, we’ll need to modify child AppChildComponent as shown in the listing below:

As you notice, we have modified the greetMessage property with the @Input() decorator. Also, we have implemented onInit, which will be used in demos later. So essentially, in the child component, we have decorated the greetMessage property with the @Input() decorator so that value of greetMessage property can be set from the parent component.

Next, let us modify the parent component AppComponent to pass data to the child component.

From the parent component, we are setting the value of the child component’s property greetMessage. To pass a value to the child component, we need to pass the child component property inside a square bracket and set its value to any property of parent component. We are passing the value of childmessage property from the parent component to the greetMessage property of the child component.

image

Intercept input from parent component in child component

We may have a requirement to intercept data passed from the parent component inside the child component. This can be done using getter and setter on the input property.

Let us say we wish to intercept an incoming message in the child component, and combine it with some string. To achieve this, we created a property called _greetmessage and using @Input() decorator creating getter and setter for _greetmessage property. In the getter, we’re intercepting the input from the parent component and combining it with the string. This can be done as shown in the next listing:

In the setter, we are manipulating incoming data from the parent component and appending some text to that. Keep in mind that the behavior of the parent component would not change whether we are intercepting the message or not. To explore it further, let us take another example and create a child component, which will display names passed from the parent. If the parent passes empty name value, then the child component will display some default name. To do this, we have modified the setter in the child component. In the setter, we are checking whether the name value is passed or not. If it is not passed or it is an empty string, the value of name would be assigned to a default value. The child component can be created as shown in the listing below:

Read full article on the Infragistics blog

Different ways of injecting dependency in an AngularJS Application

When you start learning the very first characteristics of AngularJS, you may come across something called Dependency Injection (DI): the premise that AngularJS injects dependencies whenever an application needs them. As a developer, our task is only to pass the dependency to the module and everything else will be taken care by AngularJS.

To create a controller, we pass $scope object and other dependencies to the module’s controller function. For example, to create a ProductController, we are passing $scope object and Calculator service dependencies. As a developer our job is to pass the dependencies and AngularJS will inject them whenever the application needs them.

As a developer, we really don’t care about how AngularJS injects dependencies – we don’t need to know how the injection process works to develop applications.  However, it is better if we know different ways of passing dependencies. In AngularJS, dependencies can be passed in three possible ways. They are as follows:

  • Passing a dependency as Function Arguments
  • Passing a dependency as Array Arguments
  • Passing a dependency using the $inject service

Let us explore these options one by one.

Passing a dependency as a Function Argument

Perhaps most of the time you pass a dependency as a function argument, which is perfectly fine. For example, we pass a $scope object to create a controller as shown in the listing below:

Read full article on the Infragistics blog

What is a Provider () in AngularJS?

The provider() function allows us to create a configurable service where we can set input per application for the service created using the provider (). For example, if we need to set API key to access a service on the application level, we can set that in the module config and pass input to the provider using the $provide service. All the others ways to create services internally use the $provide service.

Creating a service using $provide service in module.config

Let us start by creating a very simple service using the provider() function.

	
app.config(function ($provide) {
    $provide.provider('globalsetting', function () {
        this.$get = function () {
            var appname = "Lawyer App";
            return {
                appName: appname
            };
        }
    })
});

Let’s explore what is going on in the above snippet. To create a service using provider, we need to use the $provide service. The provider function of the $provide service takes two parameters: the name of the service and the function. A provider function must have a $get function. To create a simple service using the provider(), we need to perform following five steps:

  1. Inject the $provide service in the app config method
  2. Create a provider using the provider() function
  3. Pass two parameters to the provider() function: the name of the service and a function
  4. The provider function must contain a $get function
  5. Return an object literal from the $get function

We can use the globalsetting service created using the provider by injecting it in a controller as shown in the listing below:

Read full article on the Infragistics blog

Services in AngularJS simplified with examples

Read: 21 points cheat sheet on AngularJS controller and the $scope object

What is service?

  • It provides us method to keep data across the lifetime of the angular app
  • It provides us method to communicate data across the controllers in a consistent way
  • This is a singleton object and it gets instantiated only once per application
  • It is used to organize and share data and functions across the application

Two main execution characteristics of angular services are that they are singleton and lazy instantiated. Angular only creates instance of a service when an application component depends on it. On the other hand each application component dependent on the service work with the single instance of the service created by the angular.

image

Keep in mind that services are singleton object and gets instantiated once per angular app using the $injector and they gets created when angular app components need them.

Let us start with creating a very simple service. This service will find square of a given number. It is a good idea to put all the service in a separate JavaScript file. We have created service.js file and inside that creating a service or registering a service using the service method as shown below,

var CalculatorService = angular.module('CalculatorService', [])
.service('Calculator', function () {
    this.square = function (a) { return a*a};

});

An AngularJS service can be created or registered or created in four different ways,

  1. Using the service() method
  2. Using the factory() method
  3. Using the provider() method
  4. Using the value() method
  5. Using the constant() method

Further in the post we will talk about other options to create the service. Above we have created the calculator service using the service() method.

To use the service in the controller, we are passing the service module CalculatorService as dependency in the application module. Next in the controller we are passing name of the service Calculator to be used.

var myApp = angular.module('myApp', ['CalculatorService']);
myApp.controller('CalculatorController', function ($scope, Calculator) {

    $scope.findSquare = function () {
        $scope.answer = Calculator.square($scope.number);
    }
});

On the view we are using the controller to do the data binding as shown below,

<div class="container">
        <div>
            <div ng-controller="CalculatorController">
                Enter a number:
                <input type="number" ng-model="number">
                <button class="btn btn-danger" ng-click="findSquare()">Square</button>
                <div>{{answer}}</div>
            </div>
        </div>
    </div>

An angular application will render as shown below,

image

We can create a service using the factory as shown below. We are creating the service to reverse the string.

CalculatorService.factory('StringManipulation', function () {

   var r=  function reverse(s) {
        var o = '';
        for (var i = s.length - 1; i >= 0; i--)
            o += s[i];
        return o;
    }

   return{
       reverseString: function reverseString(name)
       {
           return r(name);
       }
   }

});

In the controller the StringManipulationService can be used as shown below:


myApp.controller('CalculatorController', function ($scope, Calculator) {

    $scope.findSquare = function () {
        $scope.answer = Calculator.square($scope.number);
    }
});

On the view we are using the controller to do the data binding as shown below,

<div ng-controller="StringController">
                Enter Name:
                <input ng-model="name">
                <button class="btn btn-info" ng-click="findReverse()">Reverse Name</button>
                <div>{{reversename}}</div>
            </div>

An angular application will render as shown below,

image

Let us understand difference between creating a service using the service() method and the factory() method.

  1. Using the service() method uses the function constructor and it returns the object or instance of the function to work with
  2. Using the factory() method uses the returned value of the function. It returns the value of the function returned after the execution

If we want to register a service using the function constructor, in that scenario we will use service() method to register the service. If we use factory() method to register the service it returns the value after execution of the service function. It can return any value like primitive value, function or object. So service() method returns the function object whereas factory() method can return any kind of value.

In further post we will talk about other ways of creating service. Now let us work on a full working example of using service in an angular app. We are going to create an application which will perform the followings,

  1. List students from the database
  2. Add a student to the database

Roughly architecture of the application can be drawn as shown below,

image

This post will not cover how to create a JSON based WCF REST Service. With the assumption that REST based service is already in place to retrieve the students and add a student, we will write the angular application.

The Service

var StudentService = angular.module('StudentService', [])
StudentService.factory('StudentDataOp', ['$http', function ($http) {

    var urlBase = 'http://localhost:2307/Service1.svc';
    var StudentDataOp = {};

    StudentDataOp.getStudents = function () {
        return $http.get(urlBase+'/GetStudents');
    };

    StudentDataOp.addStudent = function (stud) {
        return $http.post(urlBase + '/AddStudent', stud);
    };
    return StudentDataOp;

}]);

We are creating the service using the factory(). There are two methods in the service. getStudents fetch all the students using the $http.get whereas addStudent add a student using the $http.post. In the service we are using other inbuilt angular service $http to make the call to the service. To use the $http service, we have to pass this as dependency to the service factory() method.

Once service is created, let us create the controller which will use the service to perform the operations.

The Controller 

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

myApp.controller('StudentController', function ($scope, StudentDataOp) {
    $scope.status;
    $scope.students;
    getStudents();

    function getStudents() {
        StudentDataOp.getStudents()
            .success(function (studs) {
                $scope.students = studs;
            })
            .error(function (error) {
                $scope.status = 'Unable to load customer data: ' + error.message;
            });
    }

    $scope.addStudent = function () {

        var stud = {
            ID: 145,
            FirstName: $scope.fname,
            LastName: $scope.lname
        };
        StudentDataOp.addStudent(stud)
            .success(function () {
                $scope.status = 'Inserted Student! Refreshing Student list.';
                $scope.students.push(stud);
            }).
            error(function (error) {
                $scope.status = 'Unable to insert Student: ' + error.message;
            });
    };
});

In the controller we are adding getStudents and addStudents functions to scope. As it is clear from the name that these functions are used to fetch students and add student respectively. As a dependency StudentSevice module is passed in the module and in the controller we are passing the StudentDataOp service as the dependency.

Other important thing to notice is that, we are creating student object to be added using the $scope object properties like fname and lname. These properties are set to the $scope on the view.

The View

View is very simple. StudentController is attached to the view. There are two section in the view. In first section we are taking user input to create the student. In the second section, in a table all the students are listed.

<div ng-controller="StudentController">
            <form class="well">
                <input type="text" name="fname" ng-model="fname" placeholder="first name" /> <br/>
                <input type="text" name="lname" ng-model="lname" placeholder="last name" />
                <br /><br/>
                <input type="button" value="add student" ng-click="addStudent()" class="btn btn-primary" />
            </form>
            <br/>
            <table class="table">
                <tr ng-repeat="s in students">
                    <td>{{ s.FirstName }}</td>
                    <td>{{ s.LastName }}</td>
                    <td>
                        <a href="#" class="btn btn-info" ng-click="edit(contact.id)">edit</a>
                        <a href="#" class="btn btn-danger" ng-click="delete(contact.id)">delete</a>
                    </td>
                </tr>
            </table>
        </div>

In the input form we are setting fname and lname properties on the $scope object and then calling addStudent() function of the controller to add a student to the database.

In the table using the ng-repeat directive all the students are listed. We have put two buttons for edit and delete. These buttons are not performing any task as of yet. In further posts we will add edit, delete and search functionality.

If you are following along the posts, may be you want to these functionality of your own and share experience with me.

On running the application, you will get form to add a student and all students listed in the table.

clip_image002

This is how you can create and use angularJS service in application. I hope you find this post useful. Thanks for reading. Happy coding.

Learn AngularJS Hour 5: All about $scope object

In hour 1 , we learnt to get started with AngularJS.

In hour 2 , we learnt about AngularJS Template.

In hour 3 , we learnt about two way bindings and filter.

On hour 4 , we learnt about $http service and making HTTP operations.

In 5th hours of series, we will learn about $scope in Angular. $scope is an object which connects View and Controller together.

 

image

To understand $scope better let us start with first angular app we wrote,

image

Above program ran and due to $rootScope of angular. When you don’t provide any $scope explicitly, angular works with $rootScope. To understand $rootScope better let us understand below diagram,

image

We have added attribute name in $rootScope under the main function. Main function can be considered as main method of angular app. Since attribute is added to $rootScope, it can be accessed anywhere on the view and we do not need controller to access this. Due to $rootScope hello world ng-model of textbox got rendered on the view with template {{name}}.

For complex application you will have to create explicit $scope. Consider we have a view as below,


<div ng-controller="authorController" >
        {{author.name}} is {{author.age}} old
    </div>

Here we have attach a controller object to div element of DOM in view. Now to make sure that author.name and author.age attribute is available on the view, we need to create explicit $scope. That can be created as below,


app.controller('authorController', function ($scope) {
    $scope.author = {
        name: "Dhananjay Kumar",
        age: 32
    };
});

Attribute author of authorController will be available to all child element of the div to which authorController is attached. For example consider below View, we are able to read value of author attribute in child div as well,

  <div ng-controller="authorController" >
        <div>
            I am in child div  <br/>
            {{author.name}} is {{author.age}} old
        </div>
    </div>

We can summarize few points about $scope as follows,

  • $scope ties view and controller together
  • $scope provides an execution context in which DOM element is bound
  • In context of MVC , $scope can be seen as model
  • View and model both have access of $scope
  • $scope holds data and functions from controller that should be displayed and get executed in view
  • $rootScope is top most scope in on DOM element with ng-app directive

In angular all the $scope are created with prototypal inheritance. All $scope has access to their parent scope. For above example $scope of authorController has access to $rootScope. On the view $scope of child controller can access attributes of parent controller. To understand it better, let us create two controllers. authorController is parent controller and childAuthorController is child controller. You can see in the child controller childAuthorController that author attribute of authorController


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

app.controller('authorController', function ($scope) {
    $scope.author = {
        name: "Dhananjay Kumar",
        age: 32
    };
});

app.controller('childAuthorController', function ($scope) {

    $scope.hello = function()
    {
        alert($scope.author.name);
    }
})


On the view we have two div, first div is attached to parent controller whereas second view is attached to child controller.


<div ng-controller="authorController" >
        <div ng-controller="childAuthorController">
            
            {{author.name}} is {{author.age}} old
            <button ng-click="hello()" class="button" >say Hello</button>
        </div>       
    </div>

You can see that we have access of parent controller attributes inside DOM element which is attached with child controller.

$scope work on prototypal inheritance in angular. Diagrammatically we can show that as follows,

image

This is the way $scope object works in angular. Even though it performs complex tasks like binding controller and view together at the end of the day it is simple JavaScript object. Having a good knowledge on $scope is big help in implementing complex angular applications. Happy coding.