• [Angular] @ContentChild with Directive ref


    For example you have a component, which take a trasclude input element:

                <au-fa-input id="password-field" icon="lock" >
                    <input placeholder="Password" class="test-class">
                </au-fa-input>

    There is many ways to get ElementRef of the input, for example using Reference:

                <au-fa-input id="password-field" icon="lock" >
                    <input #input placeholder="Password" class="test-class">
                </au-fa-input>

    We add a #input ref, so that inside component, we can using @ContentChild and AfterContentInit lifecycle:

    export class AuFaInputComponent implements AfterContentInit{
    
        @Input()
        icon: string;
    
        @ContentChild('input')
        input: HTMLInputElement;
    
        ngAfterContentInit () {
          console.log("input", this.input);
        }

    This approach works fine, but it requires us to put a element ref onto the input field.

    One way to avoid putting a reference is creating a directive ref, and we can add common functionalitiy to it, such as focus and blur events:

    import {Directive, HostListener} from '@angular/core';
    
    @Directive({
        selector: 'au-fa-input input'
    })
    export class InputRefDirective {
    
      focus = false;
    
      @HostListener('focus')
      isFocus() {
        console.log("now focus");
        this.focus = true;
      }
    
      @HostListener('blur')
      isBlur() {
        console.log("now blur");
        this.focus = false;
      }
    }

    And we our component, we need to change @ContentChild:

        @ContentChild(InputRefDirective)
        input: InputRefDirective;

    So for now, in html, we don't need #input any more:

                <au-fa-input id="password-field" icon="lock" >
                    <input placeholder="Password" class="test-class">
                </au-fa-input>

    Now, let's say if we want to add some styling base on whether input field is focused or not.

    First, some css class:

    // component
    
    :host(.input-focus) {
      border-color: #4D90FE;
      -webkit-box-shadow: 0 0 5px  #4D90FE;
      box-shadow: 0 0 5px  #4D90FE;
    }

    Use the function form to apply host styles conditionally by including another selector inside parentheses after :host. So here, we check if .input-focus is present on the host element, then we apply the styling, otherwise not.

    Now we only need to apply .input-focus class to the host element when input.focus is true, we can do this easily by @HostBinding:

      @HostBinding('class.input-focus')
      get isInputFocus() {
        return this.input ? this.input.focus : false;
      }

    ------

    component:

    import {Component, Input, ContentChild, AfterContentInit, HostBinding} from '@angular/core';
    import {InputRefDirective} from 'app/lib/common/input-ref.directive';
    
    @Component({
      selector: 'au-fa-input',
      templateUrl: './au-fa-input.component.html',
      styleUrls: ['./au-fa-input.component.css']
    })
    export class AuFaInputComponent implements AfterContentInit {
    
      @Input()
      icon: string;
    
      @ContentChild(InputRefDirective)
      input: InputRefDirective;
    
      @HostBinding('class.input-focus')
      get isInputFocus() {
        return this.input ? this.input.focus : false;
      }
    
      ngAfterContentInit() {
        if (!this.input) {
          console.error('You forgot pass in the input field');
        }
      }
    
      get classes() {
    
        const cssClasses = {};
    
        if (this.icon) {
          cssClasses['fa-' + this.icon] = true;
        }
    
        return cssClasses;
      }
    
    }

    Directive:

    import {Directive, HostListener} from '@angular/core';
    
    @Directive({
        selector: 'au-fa-input input'
    })
    export class InputRefDirective {
    
      focus = false;
    
      @HostListener('focus')
      isFocus() {
        this.focus = true;
      }
    
      @HostListener('blur')
      isBlur() {
        this.focus = false;
      }
    }
  • 相关阅读:
    List的Select 和Select().tolist()
    lambda中FirstOrDefault和First
    EF时,数据库字段和实体类不一致问题
    用户变量问题
    实验十二:字符串和结构
    实验十一:指针(2)
    实验十:指针(1)
    实验九:二维数组和字符数组的应用
    实验八:一维数组的应用
    实验七:函数及数组(1)
  • 原文地址:https://www.cnblogs.com/Answer1215/p/6926959.html
Copyright © 2020-2023  润新知