zoukankan      html  css  js  c++  java
  • [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;
        }
    }
  • 相关阅读:
    利用jquery获取html中被选中的input的值
    获取表单选中的值(利用php和js两种方式)
    复习
    Ajax请求中的async:false/true的作用
    Jquery
    C#创建控制台项目引用Topshelf的方式,部署windows服务。
    你循环的时候就可以给他们赋值了,那么就不用addClass,再根据类选择器处理,代码能一气呵成就别写成两段了
    SQL server 数据库中插入中文变???格式乱码的问题另一种容易忽略的情况(C#操作dapper)
    SQL 两个表有关联,通过其中一个表的列,更新另一个表的列。
    SQL server 存储过程中 列传行
  • 原文地址:https://www.cnblogs.com/Answer1215/p/5870488.html
Copyright © 2011-2022 走看看