VB.net 2010 視頻教程 VB.net 2010 視頻教程 VB.net 2010 視頻教程
SQL Server 2008 視頻教程 c#入門經典教程 Visual Basic從門到精通視頻教程
  • JavaScript教程之Angular:自定義表單控件

  • 2019-04-17 20:47 來源:未知

魔兽世界wow www.geyjm.icu 分享一個最近寫的支持表單驗證的時間選擇組件。

import {AfterViewInit, Component, forwardRef, Input, OnInit, Renderer} from "@angular/core";
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from "@angular/forms";
@Component({
    selector: 'time-picker',
    template: `
        <div id="container">
            <input id="input_box" readonly
                   [(ngModel)]="_value"
                   [ngStyle]="{'width.px': inputWidth, 'height.px': inputHeight}"
                   (click)="onInputClick($event)"
                   (focus)="onInputFocus($event)"
                   (blur)="onInputBlur()">
    
            <div id="panel" *ngIf="showBox">
                <div class="ui-g">
                    <div class="ui-g-4 title">小時</div>
                    <div class="ui-g-8 title">分鐘</div>
                </div>
                <div class="ui-g">
                    <div class="ui-g-4">
                        <span class="item" *ngFor="let hour of hours" [ngClass]="{'selected': hour == selectedHour}" (click)="onHourClick(hour, $event)">{{hour}}</span>
                    </div>
                    <div class="ui-g-8">
                        <span class="item" *ngFor="let minute of minutes" [ngClass]="{'selected': minute == selectedMinute}" (click)="onMinuteClick(minute, $event)">{{minute}}</span>
                    </div>
                </div>
            </div>
        </div>
    `,
    styles: [`
        :host{
            display: inline-block;
        }
        #container{
            position: relative;
        }
        #input_box{
            outline: none;
            box-sizing: border-box;
            padding: 0 3px;
        }
        #panel{
            position: absolute;
            width: 400px;
            background-color: white;
            box-shadow: 0 2px 8px 4px rgba(0,0,0,0.2);
            z-index: 2000;
        }
        .title{
            text-align: center;
        }
        .item{
            display: inline-block;
            width: 30px;
            height: 30px;
            line-height: 30px;
            text-align: center;
            cursor: pointer;
        }
        .item:hover, .item.selected{
            background-color: #0b7dd8;
            color: white;
        }
    `],
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => TimePicker), // 此時TimePicker未聲明,因此需要使用forwardRef
            multi: true
        }
    ]
})
export class TimePicker implements ControlValueAccessor, OnInit, AfterViewInit{ // ControlValueAccessor,一座表單控件和原生元素或自定義輸入組件之間的橋梁
    @Input() inputWidth = 100; // 輸入框寬度
    @Input() inputHeight = 30; // 輸入框高度
    _value: string;
    showBox = false; // 控制選擇面板顯示與否,true為顯示
    hours = []; // 小時數組
    minutes = []; // 分鐘數組
    hourIsSelect = false; // 打開選擇面板后,標記小時是否被點擊
    minIsSelect = false; // 打開選擇面板后,標記分鐘是否被點擊

    selectedHour; // 當前小時
    selectedMinute; // 當前分鐘

    bodyClickListener: any;

    constructor(
        public renderer: Renderer
    ){}

    ngOnInit(){
        for(let i = 0; i < 24; i++){
            let h;
            if(i < 10){
                h = '0' + i;
            }else{
                h = '' + i;
            }
            this.hours.push(h);
        }
        for(let j = 0; j < 60; j++){
            let m;
            if(j < 10){
                m = '0' + j;
            }else{
                m = '' + j;
            }
            this.minutes.push(m);
        }
    }

    ngAfterViewInit(){
        this.bodyClickListener = this.renderer.listenGlobal('body','click', () => { this.hide() });
    }

    onChange = (time: string) => {};
    onTouched = () => {};

    get value(): string{
        return this._value;
    }

    set value(val: string){
        if(val !== this._value){
            this._value = val;
            this.onChange(val);
        }
    }

    /**
     * 實現ControlValueAccessor中的方法,用于將model顯示到view
     * @param val
     */
    writeValue(val: string): void{
        if(val !== this._value){
            this._value = val;
        }
        if(this._value){
            let time = this._value.split(':');
            this.selectedHour = time[0];
            this.selectedMinute = time[1];
        }
    }

    /**
     * 實現ControlValueAccessor中的方法,用于通知Angular值已被修改
     * @param fn
     */
    registerOnChange(fn: (time: string) => void): void{
        this.onChange = fn;
    }

    /**
     * 實現ControlValueAccessor中的方法,用于通知Angular輸入框被鼠標聚焦過
     * @param fn
     */
    registerOnTouched(fn: () => void): void{
        this.onTouched = fn;
    }

    /**
     * 隱藏選擇面板
     */
    hide(){
        this.showBox = false;
        this.hourIsSelect = false;
        this.minIsSelect = false;
    }

    /**
     * 顯示選擇面板
     */
    show(){
        this.showBox = true;
    }

    /**
     * 輸入框獲得焦點
     * @param event
     */
    onInputFocus(event){
        event.stopPropagation();
        this.show();
    }

    /**
     * 輸入框失去焦點
     */
    onInputBlur(){
        this.onTouched();
    }

    /**
     * 輸入框點擊
     * @param event
     */
    onInputClick(event){
        event.stopPropagation();
    }

    /**
     * 選擇小時
     * @param h
     * @param event
     */
    onHourClick(h, event){
        event.stopPropagation();

        this.selectedHour = h;
        this.value = this.selectedHour + ':' + (this.selectedMinute ? this.selectedMinute : '00');

        this.hourIsSelect = true;
        if(this.hourIsSelect && this.minIsSelect){
            this.hide();
        }
    }

    /**
     * 選擇分鐘
     * @param min
     * @param event
     */
    onMinuteClick(min, event){
        event.stopPropagation();

        this.selectedMinute = min;
        this.value = (this.selectedHour ? this.selectedHour : '00') + ':' + this.selectedMinute;

        this.minIsSelect = true;
        if(this.hourIsSelect && this.minIsSelect){
            this.hide();
        }
    }
}
相關教程