Learn Angular JS2 with Paras Mendiratta in 31 days — Day #5

Introduction to Directives

Paras Mendiratta
4 min readJan 16, 2017
Draggable Containers

For those who are coming first time to my this blog: We are building an online planner similar to Google Keep.You can see more details over here: Tutorial Series

There are three types of directives in Angular JS 2

  1. Component Level — directives with template (Template in @Component)
  2. Structural Level — Changes the DOM layout by adding or removing component (NgIf or NgFor)
  3. Attribute Level — Changes the appearance or behaviour of the component

While the first two kinds we have already used in our project. Today we will be talking about the third kind.

We will be creating two custom attribute directive for HTML layout and we will importing one 3rd party attribute directive for drag and drop of elements.

Also we will be demoing use case for Structural directive for building up this example.

Anatomy of Directive

To demonstrate the usage of directive, I checked the support of Material for Angular JS 1 and Angular JS 2. I found that lot of directives are missing. One of them is ‘md-flex’.

md-flex directive is responsible for providing the flex based decoration in Material Angular JS #1. However this is missing in Material Angular JS 2 at the point of writing this article.

So I created similar directive and calling it sd-flex’ i.e. Silver Doe Flex. Here is sample code.

import { Directive, ElementRef, Input } from '@angular/core';@Directive({
selector: '[sd-flex]'
})
export class SDFlexDirective {@Input('sd-flex') flexValue: number;constructor (private el: ElementRef) {
el.nativeElement.style.display = 'block';
}
ngOnInit() {
this.setWidthBasedOnFlex(this.flexValue);
}
private setWidthBasedOnFlex(value: number) {
value = value ? value : 100;
value = Math.abs(value);
value = Math.max(value, 1);
value = Math.min(value, 100);
//value = value / 100;
this.el.nativeElement.style.flexGrow = 1;
this.el.nativeElement.style.flexShrink = 1;
this.el.nativeElement.style.flexBasis = value + '%';
//this.el.nativeElement.style.width = '' + value + '%';
}
}

Let’s dissect the code one by one:

import { Directive, ElementRef, Input } from '@angular/core';

Here, we are importing the Directive, ElementRef and Input from Angular Core Library.

@Directive({
selector: '[sd-flex]'
})

In above mentioned code, we are referring attribute selector for the directive. For example the following code,

<div id="parent">
<div sd-flex="55">Hello</div>
<div sd-flex="44">Bye</div>
</div>

will result in dividing parent div element into two sections. One having 55% of horizontal space and second will be having 44% of horizontal space. It will look like as shown below.

Flex Directive Example

So how this is going to work out. Let’s see further in class level details. Let’s define the class.

export class SDFlexDirective { @Input('sd-flex') flexValue: number;constructor (private el: ElementRef) {
el.nativeElement.style.display = 'block';
}
}

In the above code, we have define the class body and also mentioned that ‘sd-flex’ will have input value of type number. In the constructor body we are getting ElementRef as private variable and we are assigning the display style as ‘block’.

Now to assign the flex value, we first need to wait to get the value being parsed by Angular Engine.

Angular does not instantly parsed the value. But it do it when ngOnInit() function is called. This function is called automatically whenever Angular is initialised. So here we can get the directive input value.

Let’s see the code for it.

ngOnInit() {
this.setWidthBasedOnFlex(this.flexValue);
}
private setWidthBasedOnFlex(value: number) {
value = value ? value : 100;
value = Math.abs(value);
value = Math.max(value, 1);
value = Math.min(value, 100);
// Assign the flex values.
this.el.nativeElement.style.flexGrow = 1;
this.el.nativeElement.style.flexShrink = 1;
this.el.nativeElement.style.flexBasis = value + '%';
}
}

So, in ngOnInit function we got the flexValue that was added in directive and then we set the value in separate private function.

So, I hope it would have cleared up some concepts on directives. In future post, we will see some more complex examples of directives.

In the current release, we have created four directive and bind them in common module so that all of them can be used at once.

  1. sd-flex directive — similar to md-flex directive in Material Angular JS #1
  2. sd-layout directive — similar to layout directive in Material Angular JS #1
  3. sd-layout-wrap directive — similar to layout-wrap directive in Material Angular JS #1
  4. sd-text-center directive — center aligns text in child elements

Also we have used one of the third party directive for dragging and dropping the goals in the goal container. Here is the link to that:

You can see the relative implementation in layout.component.ts file. Here is the link to that:

You can even download complete code from here:

Tomorrow, we will discuss about enhancing HTML design for Planner Component and let’s try to make is close as we designed in photoshop.

Journey Links:

--

--