First, what's directive, what's the difference between component and directive.
For my understanding,
- Component is something like ' canvas ', ' form ', ' table ' ... they has the template and their own functionality. It defines how a HTML tags should work like and look like.
- directive is something like ' ngif ', ' Required ', ' checked ' ... they don ' t necessary to has their own template (of course th EY can have). It Change the original component-to-work or looks-like.
Basic ' directive ' and ' component ' they is quite similar, so just follow the rules when you want to choose using ' Directiv E ' or ' component ':
- Add something new to the DOM with its own template, using component
- Modify something (can be functionality or template) already in teh DOM, using directive.
What we want to build is collapse directive:
When you double click the panel, it'll toggle the content show/hide and change the icon.
Also When you click on the button which outside the panel, you'll Also be able to toggle the panel.
So it requires know
- How to deal with Host Elm ' events-- @HostListener
- How to deal with Host Elm ' s attrs- @HostBinding
- How to export directive as API for the component which stay outside the host Elm to and Exportas
First. Let's see how to toggle it by using @HostListener & @HostBinding:
The host element HTML:
collapse-on- Click class= "card Card-strong disable-text-selection" > <i class= "Md-icon Collapsible-indicator ">arrow_drop_down</i> <i class=" Md-icon collapsible-indicator ">arrow_ drop_up</i> <div class= "collapsible-section" > double click it and it would collapse or expand. </div> </div>
Css:
. collapsed. collapsible-section{ display:none;}
directive
Import{Directive, Hostlistener, hostbinding} from "@angular/core"; @Directive ({selector:' [Collapse-on-click] '}) ExportclassCollapseonclick {collapsed:Boolean; Constructor () { This. collapsed =false; } //set "collapsed" class to the host element according to//this.collapsed Value@HostBinding (' class.collapsed ') Get isCollapsed () {return This. Collapsed; } //if the double click the host element, the'll fire toggle function@HostListener (' DblClick ') Toggle () { This. collapsed =! This. Collapsed; }}
So everytime, if you double click the host element, it'll run 'toggle ()' function, it'll change 'this.c ollapsed' value to True or false. Then we had a getter and setter to get and set 'this.collapsed'. According to 'this.collapsed', we'll add 'collapsed' class to host element. This class would help to hide the content, as we define in CSS file.
So when toggle:true:the host HTML would change to:
<Collapse-on-click classcollasped">
When Toggle:false:
<Collapse-on-click class= "card Card-strong disable-text-selection" >
To switch the icon, we can use the template reference from directive:
@Directive ({ ' [Collapse-on-click] ', exportas' collapsible '})
We define Exportas, which we can refer in host HTML:
<Divcollapse-on-click #panel = "Collapsible"class= "card Card-strong disable-text-selection"> <Iclass= "Md-icon collapsible-indicator" *ngif= "!panel.collapsed" >Arrow_drop_down</I> <Iclass= "Md-icon collapsible-indicator" *ngif= "panel.collapsed" >Arrow_drop_up</I> <Divclass= "Collapsible-section" >This page is collapsible, double click it and it'll collapse or expand. </Div> </Div>
And one improvement for using template Reference are we not longer need to depend on a CSS class ' collapsed ', to s How/hide the content, we can just use ngif.
<DivCollapse-on-click #panel= "Collapsible"class= "card Card-strong disable-text-selection"> <Iclass= "Md-icon collapsible-indicator"*ngif= "!panel.collapsed">Arrow_drop_down</I> <Iclass= "Md-icon collapsible-indicator"*ngif= "panel.collapsed">Arrow_drop_up</I> <Divclass= "Collapsible-section" *ngif= "!panel.collapsed" >This page is collapsible, double click it and it'll collapse or expand. </Div> </Div>
This is the can make of the direcitve more reuseable.
Another benifite for using tempalte reference are, we can call directive function or access directive props by ref.
<DivCollapse-on-click #panel= "Collapsible"class= "card Card-strong disable-text-selection"> <Iclass= "Md-icon collapsible-indicator"*ngif= "!panel.collapsed">Arrow_drop_down</I> <Iclass= "Md-icon collapsible-indicator"*ngif= "panel.collapsed">Arrow_drop_up</I> <Divclass= "Collapsible-section"*ngif= "!panel.collapsed">This page is collapsible, double click it and it'll collapse or expand. </Div> </Div> <HR/> <Button(click)= "panel.toggle ()">Toggle: {{panel.collapsed}}</Button>
So, we add a button, which stay outside the host element. When it clicked, it would also call the toggle () method on directive to show/hide the content.
Notice:another to write @HostListener:
@Directive ({ ' [Collapse-on-click] ', ' collapsible ', host: { ' ( DblClick) ': ' Toggle () ' }})
It is also clear.
------------------
App.ts:
Import {Component} from "@angular/core"; import {ngmodule} from"@angular/core"; import {platformbrowserdynamic} from"@angular/platform-browser-dynamic"; import {browsermodule} from"@angular/platform-browser"; import {Collapseonclick} from"./collapse-on-click.directive"; @Component ({selector:' App ', Template: '<div Collapse-on-click #panel = "collapsible"class= "card Card-strong disable-text-selection" > <i class= "Md-icon collapsible-indicator" *ngif= "!panel.collap Sed ">arrow_drop_down</i> <i class=" Md-icon collapsible-indicator "*ngif=" panel.collapsed ">arrow_ drop_up</i> <div class= "collapsible-section" *ngif= "!panel.collapsed" >This page is collapsible,DoubleClick it and it'll collapse or expand. </div> </div> `}) Export class App {} @NgModule ({declarations: [app, Collapseonclick], imports: [Browsermodule], Bootstrap: [App]}) Export class Appmodule {}platformbrowserdynamic (). Bootstrapmodule (appmodule);
Collapsed-on-click.ts:
Import {Directive, Hostlistener, hostbinding} from "@angular/core"; @Directive ({selector:' [Collapse-on-click] ', Exportas:' Collapsible '}) Export class Collapseonclick {collapsed:Boolean; Constructor () { This. collapsed =false; } //set "collapsed" class to the host element according to //this.collapsed Value /*@HostBinding (' class.collapsed ') get isCollapsed () {return this.collapsed; }*/ //if the double click the host element, the'll fire toggle function@HostListener (' DblClick ') Toggle () { This. collapsed =! This. Collapsed; }}
[Angular 2] Directive Intro and Exportas