物聯網平臺設計心得:DateTimePicker實現選擇聯動

所謂的選擇聯動,就是指,當我DateTimePicker1選擇2月4號的時候,我DateTimePicker2只能選擇2月4號和2月5號兩天,固然你能夠自行規定要選擇的日期。這在一些圖表查詢條件裏面是很經常使用的一個功能。下面咱們就來看看如何設計。css

DateTimePicker的選取與使用html

在這裏,咱們使用的DateTimePicker是一個開源的組件,他的model名稱爲:ui.bootstrap.datetimepicker,咱們能夠去這個網址找到其相關的內容:http://dalelotts.github.io/angular-bootstrap-datetimepicker/,而後下載其相應的包,最後放到項目中,並進行引用便可(注意不能少了moment.js,它是構建與這個組件的基礎上):git

    <!--DateTimePicker Part-->
    <link href="~/Content/front/angular-datetimepicker/css/datetimepicker.css" rel="stylesheet" />
    <script src="~/Content/front/angular-datetimepicker/js/moment.js"></script>
    <script src="~/Content/front/angular-datetimepicker/js/zh-cn.js"></script>
    <script src="~/Content/front/angular-datetimepicker/js/datetimepicker.js"></script>

而後在module中進行註冊:github

var app = angular.module('dsBootstrap', [
                                        'ui.grid',
                                        'ui.grid.selection',
                                        'ui.grid.pagination',
                                        'ngCookies',
                                        'ui.bootstrap.datetimepicker'
                                        ]);

最後在HTML頁面進行排版佈局使用便可:bootstrap

  <div class="row" ng-show="visible">
            <div class="col-md-4">
                <div class="input-group">
                    <span class="input-group-addon" id="basic-addon1">開始時間:</span>
                    <div class="dropdown">
                        <a class="dropdown-toggle" id="starttime" role="button" data-toggle="dropdown" data-target="#" href="#">
                            <div class="input-group">
                                <input type="text" class="form-control" data-ng-model="starttime|date:'yyyy-MM-dd' "><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
                            </div>
                        </a>
                        <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
                            <datetimepicker data-ng-model="starttime" data-on-set-time="onTimeSet(newDate, oldDate)" data-datetimepicker-config="{ dropdownSelector: '#starttime',startView:'day', minView:'day' }" />
                        </ul>
                    </div>
                </div>
            </div>
            <div class="col-md-4">
                <div class="input-group">
                    <span class="input-group-addon" id="basic-addon1">結束時間:</span>
                    <div class="dropdown">
                        <a class="dropdown-toggle" id="endtime" role="button" data-toggle="dropdown" data-target="#" href="#">
                            <div class="input-group">
                                <input type="text" class="form-control" data-ng-model="endtime|date:'yyyy-MM-dd' "><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
                            </div>
                        </a>
                        <ul class="dropdown-menu" id="endContainer" role="menu" aria-labelledby="dLabel">
                            
                        </ul>
                    </div>
                </div>
            </div>
           
        </div>

這樣咱們就完成了第一步的工做了。從上面的Html代碼咱們能夠看出,starttime和endtime是傳遞到controller中的所選擇的日期值。並且咱們的endtime DateTimePicker咱們並無放到前臺,咱們須要在後臺動態生成。爲何呢?由於咱們須要根據StartTime的選取值,來計算出endTime的選取範圍,因此這裏須要動態生成綁定。cookie

DateTimePicker的聯動app

下面咱們開始設計其聯動工做。less

首先,當選擇開始時間後,會進入onTimeSet事件,在這個事件中,咱們先動態生成結束時間選擇器:oop

    $scope.onTimeSet = function (newDate, oldDate) {
        var startTimeFmt = moment($scope.starttime).format("YYYY-MM-DD");
        var endTimeFmt = moment(startTimeFmt).add(1, 'day').format("YYYY-MM-DD");
     
        //時間框置空
        $("#endtime input").val("");
        //移除原有的datetimepicker對象
        $("#endContainer").children().remove();
        //設置config
        $scope.config = { dropdownSelector: "#endtime", startView: "day", minView: "day" };
        //動態編譯datetimepicker directive
        var compiledeHTML = $compile('<datetimepicker data-ng-model="endtime"  data-before-render="beforeRender($view, $dates, $leftDate, $upDate, $rightDate)" data-datetimepicker-config="{{config}}" />')($scope);
        //放入html容器
        $("#endContainer").append(compiledeHTML);
    }

而後,當上面的方法執行到$compile的時候,就會觸發其beforeRender事件,此事件容許在控件加載前,進行一些相關操做。咱們利用這個事件,拋出一個days-check事件,以便動態加載時間範圍:佈局

    //當選擇開始時間,會進入onTimeSet事件,執行到$compile的時候,就會觸發下面的beforeRender事件
    //觸發beforeReder事件後,會拋出一個days-check事件出去,並附帶全部的當頁時間對象。
    $scope.beforeRender = function ($view, $dates, $leftDate, $upDate, $rightDate) {
        $timeout(function () {
            $scope.$broadcast('days-check', $dates);
        });
    }

最後,咱們接收這個事件:

    //接收事件,並重置頁面
    $scope.$on('days-check', function (e, d) {
        for (var i = 0; i < d.length; i++) {
            //初始設置爲不可選狀態,不選中狀態
            d[i].active = false;
            d[i].selectable = false;
            //當前loop的值
            var currentDate = moment(d[i].utcDateValue).format("YYYY-MM-DD");
            //當前選定的開始時間
            var startTimeFmt = moment($scope.starttime).format("YYYY-MM-DD");
            //容許選定的最大的結束時間
            var endTimeFmt = moment(startTimeFmt).add(1, 'day').format("YYYY-MM-DD");
            //比較並設置可選日期
            if (currentDate >= startTimeFmt && currentDate <= endTimeFmt) {
                d[i].selectable = true;
            }
        }
    });

當咱們收到這個days-check事件的時候,咱們會首先重置全部日期爲不可選狀態,而後根據預先設定的值,來肯定選取範圍。 這樣,經過上面的設置,咱們的結束時間就能根據開始時間的選擇而進行聯動了。是否是很方便呢?最後附上controller整體代碼:

app.controller('collectorController', ['$scope', '$cookies', '$timeout','$compile', 'baseService', 'collectorService', 'uiGridConstants', function ($scope, $cookies,$timeout,$compile, baseService, collectorService, uiGridConstants) {
    var self = this;

    $scope.ProvinceData = null;
    $scope.CityData = null;
    $scope.DistrictData = null;
    $scope.CompanyData = null;
    $scope.MachineData = null;
    $scope.RealTimeData = null;
    $scope.HistoryData = null;

    $scope.selectedProvince = null;
    $scope.selectedCity = null;
    $scope.selectedDistrict = null;
    $scope.selectedCompany = null;
    $scope.selectedMachine = null;

    $scope.starttime = null;
    $scope.endtime = null;

    $scope.visible = false;  //datetimepicker是否顯示

    //art.dialog({ title: '加載提示', icon: 'face-smile', fixed: true,left:'50%',top:0, time:3, content: "日期選擇跨度不要過大,不然會由於數據量過大而沒法加載圖表和列表!", padding: 0 });

    //監測省份的變化,若是發生了變化,則加載城市列表
    $scope.$watchCollection('selectedProvince', function (oldval, newval) {
        $scope.GetCityList();
    });

    //監測城市變化,若是發生了變化,則加載地區列表
    $scope.$watchCollection('selectedCity', function (oldval, newval) {
        $scope.GetDistrictList();
    });
    //監測地區變化,若是發生了變化,則加載公司列表
    $scope.$watchCollection('selectedDistrict', function (oldval, newval) {
        $scope.GetCompanyList();
    });
    //監測公司變化,若是發生了變化,則加載機器列表
    $scope.$watchCollection('selectedCompany', function (oldval, newval) {
        $scope.GetMachineList();
    });

    //綁定列表
    $scope.gridOptions = {
        enableRowSelection: true,
        enableSelectAll: false,
        selectionRowHeaderWidth: 35,
        rowHeight: 35,
        showGridFooter: false,
        multiSelect: true,
        enablePaginationControls: true,
        paginationPageSizes: [9, 15, 20],
        paginationPageSize: 9
    };

    $scope.gridOptions.columnDefs = [
			{ name: 'Param_name', displayName: '參數名稱' },
			{ name: 'Param_unit', displayName: '參數單位' },
            { name: 'Param_data', displayName: '參數值' },
            { name: 'Param_time', displayName: '採集時間' }
    ];

    $scope.gridOptions.onRegisterApi = function (gridApi) {
        $scope.gridApi = gridApi;
    };

    //省份綁定
    collectorService.GetProvinceData().then(function (data) {
        var flag = data.data.success;
        if (flag) {
            $scope.ProvinceData = data.data.data;
            $scope.selectedProvince = baseService.getSelectedDataMapper($scope.ProvinceData, 'province');
        }
    }, null);

    $scope.GetCityList = function () {
        var selectedProvinceId;
        if ($scope.selectedProvince != undefined)
            selectedProvinceId = $scope.selectedProvince.id;
        else
            return;
        //市區綁定
        collectorService.GetCityData(selectedProvinceId).then(function (data) {
            var flag = data.data.success;
            if (flag) {
                $scope.CityData = data.data.data;
                $scope.selectedCity = baseService.getSelectedDataMapper($scope.CityData, 'city');
            }
        }, null);
    }

    $scope.GetDistrictList = function () {
        var selectedCityId;
        if ($scope.selectedCity != undefined)
            selectedCityId = $scope.selectedCity.id;
        else
            return;
        //區縣綁定
        collectorService.GetDistrictData(selectedCityId).then(function (data) {
            var flag = data.data.success;
            if (flag) {
                $scope.DistrictData = data.data.data;
                $scope.selectedDistrict = baseService.getSelectedDataMapper($scope.DistrictData, 'district');
            }
        }, null);
    }

    $scope.GetCompanyList = function () {
        var selectedDistrictId;
        if ($scope.selectedDistrict != undefined)
            selectedDistrictId = $scope.selectedDistrict.id;
        else
            return;
        //公司綁定
        collectorService.GetCompanyData(selectedDistrictId).then(function (data) {
            var flag = data.data.success;
            if (flag) {
                $scope.CompanyData = data.data.data;
                $scope.selectedCompany = baseService.getSelectedDataMapper($scope.CompanyData, 'company');
            }
        }, null);
    }

    $scope.GetMachineList = function () {
        var selectedCompanyId;
        if ($scope.selectedCompany != undefined)
            selectedCompanyId = $scope.selectedCompany.id;
        else
            return;
        //設備綁定
        collectorService.GetMachineList(selectedCompanyId).then(function (data) {
            var flag = data.data.success;
            if (flag) {
                $scope.MachineData = data.data.data;
                $scope.selectedMachine = baseService.getSelectedDataMapper($scope.MachineData, 'machine');
            }
        }, null);
    }

    //獲取實時數據
    $scope.GetRealTimeDataByMachine = function () {
        timeCheck($scope.starttime, $scope.endtime);
        var starttimeFmt = timeFmt($scope.starttime);
        var endtimeFmt = timeFmt($scope.endtime);
        //獲取實時數據
        var machineId = $scope.selectedMachine.machine_id;
        collectorService.GetRealDataList(machineId).then(function (data) {
            var flag = data.data.success;
            if (flag) {
                $scope.RealTimeData = data.data.data;
            }
        }, null);
        //獲取列表數據
        collectorService.GetHistoryDataList(machineId,starttimeFmt,endtimeFmt).then(function (data) {
            var flag = data.data.success;
            if(flag)
            {
                $scope.HistoryData = data.data.data;
                $scope.gridOptions.data = data.data.list;
            }
        }, null);
        //將級聯列表項放到cookie中,以便於以後的操做簡易化
        var expireDate = new Date();
        expireDate.setDate(expireDate.getDate() + 7);
        delete $cookies['frontselection'];

        var cookieData = JSON.stringify({
            province: $scope.selectedProvince,
            city: $scope.selectedCity,
            district: $scope.selectedDistrict,
            company: $scope.selectedCompany,
            machine: $scope.selectedMachine
        });
        $cookies.put('frontselection', cookieData, { 'expires': expireDate });
    }

    $scope.ClickToGetParamDataList = function (paramId) {
      
        timeCheck($scope.starttime,$scope.endtime);

        var starttimeFmt = timeFmt($scope.starttime);
        var endtimeFmt = timeFmt($scope.endtime);

        var machineId = $scope.selectedMachine.machine_id;
        collectorService.GetHistoryDataListByParamId(machineId, paramId, starttimeFmt, endtimeFmt).then(function (data) {
            var flag = data.data.success;
            if (flag) {
                $scope.gridOptions.data = data.data.list;
            }
        });
    }

    //顯示隱藏時間段選擇
    $scope.ClickToShowTimePicker = function () {
        $scope.visible = !$scope.visible;
    }

    $scope.onTimeSet = function (newDate, oldDate) {
        var startTimeFmt = moment($scope.starttime).format("YYYY-MM-DD");
        var endTimeFmt = moment(startTimeFmt).add(1, 'day').format("YYYY-MM-DD");
     
        //時間框置空
        $("#endtime input").val("");
        //移除原有的datetimepicker對象
        $("#endContainer").children().remove();
        //設置config
        $scope.config = { dropdownSelector: "#endtime", startView: "day", minView: "day" };
        //動態編譯datetimepicker directive
        var compiledeHTML = $compile('<datetimepicker data-ng-model="endtime"  data-before-render="beforeRender($view, $dates, $leftDate, $upDate, $rightDate)" data-datetimepicker-config="{{config}}" />')($scope);
        //放入html容器
        $("#endContainer").append(compiledeHTML);
    }

    //接收事件,並重置頁面
    $scope.$on('days-check', function (e, d) {
        for (var i = 0; i < d.length; i++) {
            //初始設置爲不可選狀態,不選中狀態
            d[i].active = false;
            d[i].selectable = false;
            //當前loop的值
            var currentDate = moment(d[i].utcDateValue).format("YYYY-MM-DD");
            //當前選定的開始時間
            var startTimeFmt = moment($scope.starttime).format("YYYY-MM-DD");
            //容許選定的最大的結束時間
            var endTimeFmt = moment(startTimeFmt).add(1, 'day').format("YYYY-MM-DD");
            //比較並設置可選日期
            if (currentDate >= startTimeFmt && currentDate <= endTimeFmt) {
                d[i].selectable = true;
            }
        }
    });

    //當選擇開始時間,會進入onTimeSet事件,執行到$compile的時候,就會觸發下面的beforeRender事件
    //觸發beforeReder事件後,會拋出一個days-check事件出去,並附帶全部的當頁時間對象。
    $scope.beforeRender = function ($view, $dates, $leftDate, $upDate, $rightDate) {
        $timeout(function () {
            $scope.$broadcast('days-check', $dates);
        });
    }

    var timeCheck = function(start,end)
    {
        if (start == null && end!=null)
        {
            art.dialog({ title: '提示', icon: 'error', time: 6, content: "必須選擇開始日期,請重試!", padding: 0 });
            return;
        }
        if (start!=null && end == null)
        {
            art.dialog({ title: '提示', icon: 'error', time: 6, content: "必須選擇結束日期,請重試!", padding: 0 });
            return;
        }
        if (start != null && end != null && start > end) {
            art.dialog({ title: '提示', icon: 'error', time: 6, content: "開始時間不能大於結束時間,請重試!", padding: 0 });
            return;
        }
    }

    var timeFmt = function(time)
    {
        if (time == null)
            time = "";
        else
            time = time.toLocaleDateString();
        return time;
    }
}]);

相關文章
相關標籤/搜索