zoukankan      html  css  js  c++  java
  • 物联网平台设计心得:DateTimePicker实现选择联动

    所谓的选择联动,就是指,当我DateTimePicker1选择2月4号的时候,我DateTimePicker2只能选择2月4号和2月5号两天,当然你可以自行规定要选择的日期。这在一些图表查询条件里面是很常用的一个功能。下面我们就来看看如何设计。

    DateTimePicker的选取与使用

    在这里,我们使用的DateTimePicker是一个开源的组件,他的model名称为:ui.bootstrap.datetimepicker,我们可以去这个网址找到其相关的内容:http://dalelotts.github.io/angular-bootstrap-datetimepicker/,然后下载其相应的包,最后放到项目中,并进行引用即可(注意不能少了moment.js,它是构建与这个组件的基础上):

        <!--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中进行注册:

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

    最后在HTML页面进行排版布局使用即可:

      <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的选取范围,所以这里需要动态生成绑定。

    DateTimePicker的联动

    下面我们开始设计其联动工作。

    首先,当选择开始时间后,会进入onTimeSet事件,在这个事件中,我们先动态生成结束时间选择器:

        $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;
        }
    }]);
    
    
  • 相关阅读:
    springboot mail+Thymeleaf模板
    jax-rs示例
    java enum的一种写法记录
    lintcode 最大子数组III
    lintcode 单词接龙II
    idea springboot热部署无效问题
    java8 Optional正确使用姿势
    Spring根据包名获取包路径下的所有类
    无状态shiro认证组件(禁用默认session)
    获取资源文件工具类
  • 原文地址:https://www.cnblogs.com/scy251147/p/5205511.html
Copyright © 2011-2022 走看看