[Angular 2] Directive intro and exportAs

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;
    }
}
复制代码

 

posted @   Zhentiw  阅读(964)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示