Angular1.X 到Angular2.0 指令迁移(时间区间选择控件)

有人可能会问,angular1.x到2.x我的代码是要废了吗,其实个人认为从想法上转变一下,大部分代码的逻辑是可以轻松复用的,本文章举个例子,把angular1.x的dateRangeSelect ,变为angular2.x的组件,ps:其实从个人经验认为2.x的入手要比1.x简单很多,没有1.x特别多的弯弯绕的概念。 http://www.daterangepicker.com/#config

首先看一下时间区间选择的1.x实现

directive部分  
angular.module('mamApp').directive('imsSelectRangeTime', [function () {  
    return {
        restrict: 'AE',
        require: '?ngModel',
        replace: true,
        templateUrl: 'templates/directives/select_range_time.html',
        scope: {
            imsSelectRangeTime: '=',
            placeholder:'='
        },
        link: function (scope, element, $attributes, ngModel) {

            var input= $(element).find('input:first');

            input.daterangepicker({
                ranges: {
                    '今天': [moment(), moment()],
                    '昨天': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
                    '过去七天': [moment().subtract(7, 'days'), moment().subtract(1, 'days')],
                    '过去30天': [moment().subtract(30, 'days'), moment().subtract(1, 'days')],
                    '这个月': [moment().startOf('month'), moment().endOf('month')],
                    '上个月': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
                },
                format: $attributes.format || 'YYYY/MM/DD',
                locale: {
                    applyLabel: "确定",
                    cancelLabel: "清空",
                    customRangeLabel: '时间段',
                    daysOfWeek: ['日', '一', '二', '三', '四', '五', '六'],
                    monthNames: ['一月', '二月', '三曰', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
                    firstDay: 1
                }
            });
            input.on('apply.daterangepicker', function (ev, picker) {
                if (scope.imsSelectRangeTime && scope.imsSelectRangeTime.onSelected) {
                    scope.imsSelectRangeTime.onSelected({
                        startDate: picker.startDate.format('X'),
                        endDate: picker.endDate.format('X')
                    }, scope);
                    scope.selectTime= picker.startDate.format('X')+ picker.endDate.format('X')
                }
            });
            input.on('cancel.daterangepicker', function(ev, picker) {
                $(this).val('');
                scope.imsSelectRangeTime.onSelected({
                    startDate: null,
                    endDate: null
                }, scope);
            });

            scope.$watch('imsSelectRangeTime.startDate', function (n, o) {
                if (n) {
                    input.data('daterangepicker').hideCalendars();//隐藏面板
                    input.data('daterangepicker').setStartDate(moment(n * 1000));
                }
            });
            scope.$watch('imsSelectRangeTime.endDate', function (n, o) {
                if (n) {
                    input.data('daterangepicker').hideCalendars();
                    input.data('daterangepicker').setEndDate(moment(n * 1000));
                }
            });


        }
    };
}]);
template html 部分

<div class="ims-range-time" style="display: inline-flex;position: relative">  
    <input  type="text" readonly placeholder="{{placeholder?placeholder:'选择时间'}}" id="time">
    <div class="line_div"></div>
    <label for="time">
        <i class="glyphicon glyphicon-calendar"   style="margin-left: -14px;margin-top: 7px; cursor: pointer;font-size: 14px;"></i>
    </label>
</div>

再来看一下时间区间选择的2.x实现(npm 需要引入jquery和moment)

/**
 * 时间区间选择
 * 返回data {startDate:'2011-09-01',endDate:'2022-01-01'}
 * onSelect
 */
import {Component, Input, EventEmitter, ElementRef} from '@angular/core';

declare var $:any;  
var $ = require('jquery');  
var moment = require('moment');  
@Component({
    selector: 'date-range-select',
    templateUrl: './dateRange.html',
    styleUrls: ['./dateRangeSelect.css']
})
export class DateRangeDirective {  
    selectTime:any="";
    dateInput:any;
    config : any ={
        ranges: {
            '今天': [moment(), moment()],
            '昨天': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
            '过去七天': [moment().subtract(7, 'days'), moment().subtract(1, 'days')],
            '过去30天': [moment().subtract(30, 'days'), moment().subtract(1, 'days')],
            '这个月': [moment().startOf('month'), moment().endOf('month')],
            '上个月': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
        },
        "showCustomRangeLabel": false,
        "alwaysShowCalendars": true,
        format: 'YYYY-MM-DD',
        locale: {
            applyLabel: "确定",
            cancelLabel: "清空",
            customRangeLabel: '时间段',
            daysOfWeek: ['日', '一', '二', '三', '四', '五', '六'],
            monthNames: ['一月', '二月', '三曰', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
            firstDay: 1
        }
    }


    @Input('option') options:any = {

    };


    constructor(private input: ElementRef) {

    }



    ngAfterViewInit() {
        let _this=this;
        let targetOptions: any = Object.assign({}, this.config, this.options);
        this.dateInput=$(this.input.nativeElement).find('input:first');
        this.dateInput.daterangepicker(targetOptions);



        this.dateInput.on('apply.daterangepicker', function (ev, picker) {
            if (_this.options && _this.options.onSelected) {
                _this.options.onSelected({
                    startDate: picker.startDate.format('YYYY-MM-DD'),
                    endDate: picker.endDate.format('YYYY-MM-DD')
                });
                _this.selectTime= picker.startDate.format('YYYY-MM-DD')+ picker.endDate.format('YYYY-MM-DD')
            }
        });
        this.dateInput.on('cancel.daterangepicker', function(ev, picker) {
            $(this).val('');
            _this.options.onSelected({
                startDate: null,
                endDate: null
            });
        });
        this.dateInput.data('daterangepicker').hideCalendars();
        this.dateInput.data('daterangepicker').setStartDate(moment(this.options.startDate));
        this.dateInput.data('daterangepicker').setEndDate(moment(this.options.endDate));
    }


}
html模版一样的,不在多写

从上面的例子可以看出,代码的逻辑基本一样,还有就是angular2 是虚拟的dom所有不能直接选择元素,需要引入ElementRef,然后就可以开心的和1.x一样写指令了。

李文杰

前端程序设计,人丑、家穷、没文化 myGit: https://github.com/JosnLee

北京市朝阳区成寿寺