First, What is directive, what is the difference between component and directive.

For my understanding,

  • component is something like 'canvas', 'form', 'table'... they have the template and their own functionality. It defines how a html tag should work like and look like.
  • directive is something like 'ngIf', 'required', 'checked'... they don't necessary to have their own template (of course they can have). It change the original component way to work or looks like.

Basic 'directive' and 'component' they are quite similar, so just follow the rules when you want to choose using 'directive' or 'component':

  1. Add something new to the DOM with its own template, using component
  2. 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 will toggle the content show / hide and change the icon.

Also when you click the button which outside the panel, you will also be able to toggle the panel.

So it requires you know

  • How to deal with Host elm's 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 use --> exportAs

First. let's see how to toggle it by using @HostListener & @HostBinding:

the host element html:

        <div 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" >
This page section is collapsible, double click it and it will collapse or expand.
</div>
</div>

css:

.collapsed .collapsible-section{
display: none;
}

directive:

import {Directive, HostListener, HostBinding} from "@angular/core";
@Directive({
selector: '[collapse-on-click]'
})
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, will fire toggle function
@HostListener('dblclick')
toggle(){
this.collapsed = !this.collapsed;
}
}

So everytime, when you double click the host element, it will run 'toggle()' function, it will change 'this.collapsed' value to true or false. Then we have a getter and setter to get and set 'this.collapsed'. According to 'this.collapsed', we will add 'collapsed' class to host element. This class will help to hide the content, as we define in css file.

So when toggle: true: the host html will change to:

<div collapse-on-click
class="card card-strong disable-text-selection collasped">

When toggle: false:

<div collapse-on-click
class="card card-strong disable-text-selection">

To switch the icon, we can use template reference from directive:

@Directive({
selector: '[collapse-on-click]',
exportAs: 'collapsible'
})

We define exportAs, which we can refer in host html:

        <div collapse-on-click #panel="collapsible"
class="card card-strong disable-text-selection">
<i class="md-icon collapsible-indicator" *ngIf="!panel.collapsed">arrow_drop_down</i>
<i class="md-icon collapsible-indicator" *ngIf="panel.collapsed">arrow_drop_up</i> <div class="collapsible-section" >
This page section is collapsible, double click it and it will collapse or expand.
</div>
</div>

And one improvement for using template reference is we not longer need to depend on a css class 'collapsed', to show / hide the content, we can just use ngIf.

        <div collapse-on-click #panel="collapsible"
class="card card-strong disable-text-selection">
<i class="md-icon collapsible-indicator" *ngIf="!panel.collapsed">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 section is collapsible, double click it and it will collapse or expand.
</div>
</div>

This way can make the direcitve more reuseable.

Another benifite for using tempalte reference is that, we can call directive function or access directive props by ref.

        <div collapse-on-click #panel="collapsible"
class="card card-strong disable-text-selection">
<i class="md-icon collapsible-indicator" *ngIf="!panel.collapsed">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 section is collapsible, double click it and it will 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 will also call the toggle() method on directive to show / hide the content.

Notice: another way to write @HostListener:

@Directive({
selector: '[collapse-on-click]',
exportAs: '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.collapsed">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 section is collapsible, double click it and it will collapse or expand.
</div>
</div>
<hr />
<button (click)="panel.toggle()">Toggle: {{panel.collapsed}}</button>
`
})
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, will fire toggle function
@HostListener('dblclick')
toggle(){
this.collapsed = !this.collapsed;
}
}

[Angular 2] Directive intro and exportAs的更多相关文章

  1. [Angular] Export directive functionalities by using 'exportAs'

    Directive ables to change component behaives and lookings. Directive can also export some APIs which ...

  2. 关于angular 自定义directive

    关于angular 自定义directive的小结 首先我们创建一个名为"expander"的自定义directive指令: angular.module("myApp& ...

  3. [Angular] Custom directive Form validator

    Create a directive to check no special characters allowed: import {Directive, forwardRef} from '@ang ...

  4. [Angular] Test Directive

    directive: import { Directive, HostListener, HostBinding, ElementRef } from '@angular/core'; @Direct ...

  5. [Angular] Using directive to create a simple Credit card validator

    We will use 'HostListener' and 'HostBinding' to accomplish the task. The HTML: <label> Credit ...

  6. angular service/directive

    <html class=" js cssanimations csstransitions" ng-app="phonecatApp" > < ...

  7. 一个Demo就懂的Angular之directive

    <body> <div ng-controller="myCtrl"> <hello-word></hello-word> < ...

  8. angular 中 directive中的多个指令

    <div ng-controller="ctrl1"> <superman weight length speed>superman</superma ...

  9. Angular中directive——scope选项与绑定策略,这个也经常迷惑的。

    开门见山地说,scope:{}使指令与外界隔离开来,使其模板(template)处于non-inheriting(无继承)的状态,当然除非你在其中使用了transclude嵌入,这点之后的笔记会再详细 ...

随机推荐

  1. visual studio 2013 配置 ef+pgsql

    环境:VS2013,WIN7 准备工作: 1.有哪些供应商提供EF6的支持? 可以看msdn给出的答案:Which providers are available for EF6? 在本文使用 Dev ...

  2. Redhat修改主机名及网络配置

    通过命令修改主机名 hostname #查看当前主机的主机名 hostname NEWHOSTNAME #临时修改当前主机名 通过配置文件修改主机名 vi /etc/sysconfig/network ...

  3. C++指针的引用

    [1]指针的引用,必须加上头文件<iomanip>因为调用类setw() 对一个数据可以使用“引用”(reference)这是C++           对C的一个重要扩充,引用是一种新的 ...

  4. 多元线性回归(Linear Regression with multiple variables)与最小二乘(least squat)

    1.线性回归介绍 X指训练数据的feature,beta指待估计得参数. 详细见http://zh.wikipedia.org/wiki/%E4%B8%80%E8%88%AC%E7%BA%BF%E6% ...

  5. 在Ubuntu6.06 在搭建SVN服务器及在windows建立svn+ssh客户端

    部门现在使用的Linux系统是Ubuntu6.06,内核版本为2.6.15-57-386.由于系统比较老,所有用网上介绍的方法搭建SVN服务器经常出错,所以参考文章[1],将自己的搭建过程记录下. 1 ...

  6. <Chapter 2>2-2-2.开发Python应用(Developing a Python App)

    对App Engine来讲最简单的Python应用是一个有两个文件的简单目录:一个称为app.yaml的配置文件,一个用于请求处理器的Python代码文件.包含app.yaml文件的这个目录就是这个应 ...

  7. 让sublime text 2更好地支持Python

    SublimeCodeIntel: ~/.codeintel/config里加了python和pythonExtraPaths的路径(Mac): {"Python" : {&quo ...

  8. Emacs Lisp 功能扩展集锦

    http://docs.huihoo.com/homepage/shredderyin/emacs_elisp.html Emacs 具有超强的扩展性.这是当今没有任何其它编辑器可以比拟 的强大特点. ...

  9. [转] GCC 中的编译器堆栈保护技术

    以堆栈溢出为代表的缓冲区溢出已成为最为普遍的安全漏洞.由此引发的安全问题比比皆是.早在 1988 年,美国康奈尔大学的计算机科学系研究生莫里斯 (Morris) 利用 UNIX fingered 程序 ...

  10. canvas绘制清晰的方法

    很早就开始使用canvas,包括自己绘制各种图形,以及作为画布提供给诸如echarts,当canvas绘制细线条,特别是关于文字绘制会出现很模糊或者锯齿的感觉. <canvas ref=&quo ...