One of the remarkable changes between Angular 1 and Angular 2 is the elimination of $scope and $rootScope. The first problem developers moving from Angular 1 to Angular 2 encounter is how to communicate between components specially in a parent-child role.

One of the situations you may face in a real world project that emphasizes the need to implement this communication, is when you use a 3rd party library, and changes happened outside of Angular 2 doesn’t mirror inside of it. Of course there are other approaches to address this issue which I’ll try to cover them in another article as well.

Assume we have a component as parent:

@Component({

selector: ‘parent-directive’,

templateUrl: ‘./path/to/parent.component.html’

}); export class ParentComponent {

public form = {

date: <Date> new Date(),

title: <string> null,

message: <string> null

} constructor() {} public onSubmit (event: any) => void;

}

I’ve tried to keep the component as simple as possible. There is only one object including the least possible details for a contact form: title, message and date.

The template for implementing this form would be just like any other HTML forms plus a few directive attributes:

<form (submit)="onSubmit($event)">

<input type="text" name="title" [(ngModel)]="form.title">

<input type="text" name="date" [(ngModel)]="form.date">

<textarea name="message" [(ngModel)]="form.message"></textarea></form>

Describing the issue

If you change the value of any of the fields (e.g. date) with a 3rd party libraries which is not ready for Angular 2 - a case you’ll face these days a lot - the change won’t affect the model: You need to tell Angular 2 about this change.

Also if you want to isolate and normalize behaviors of any 3rd party library, you’ll need a directive to wrap it and hence the communication between component and directive would be inevitable.

How to?

Now we’re trying to use a directive taking responsibility of handling dates through out the application, including this component. we’ll call it ChildComponent:

@Directive({

selector: ‘[child-directive]’

}); export class ChildDirective implements AfterViewInit {

constructor(public element: ElementRef) {} @Input('ngModel') theModel;

@Output() dateEmitter = new EventEmitter(); ngAfterViewInit() {

let datePicker = new MyDatePicker({

field: this.element.nativeElement,

onSelect: (newValue: Date) => {

this.dateEmitter.next(newDate);

}

});

}

}

A little bit more in detail

Let’s describe some parts of this directive to make it clear.

ElementRef

ElementRef returns a reference of the element on which the directive selector is added as attribute. this reference has a property named nativeElement which is a JavaScript DOM object. you can import it from ‘@angular/core’.

AfterViewInit

There are many hooks that are called during the life cycle of an Angular 2 component, here is a documentation on all of them. AfterViewInit is called as soon as Angular 2 creates the template of view and initiates child components. In this hook we can access to all the elements and their initial values. easily import it from ‘@angular/core’.

myDatePicker

Since we used a date picker 3rd party library as the example, this is the constructor of the aforementioned library which is initiated with an instance of input element using ElementRef and we’re using its onSelect method to get the selected date.

The Event emits the selected date — new value — to parent component. there you can listen it inside view using any public property from parent component. here we use the simplest approach which is an inline assignment.

<input type="text" name="date" [ngModel]="form.date" (dateEmitter)="form.date = $event" child-directive>

With the above change in the template of parent component now parent component reads the new date from the child directive. it’s worth mentioning that we could use a public function property to make any kind of changes or uses from the $event value and the $event could be from any type of variables in Javascript.

Conclusion

We no longer have access to global variables $scope and $rootScope which is a fantastic news from the performance point of view, but we need a few small changes in the approaches we used to communicate between components in Angular 1.