物联网平台设计心得: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;
}
}]);
物联网平台设计心得:DateTimePicker实现选择联动的更多相关文章
- 物联网平台设计心得:你所不知道的CRC校验
在物联网平台设计过程中,我的中间件一方面需要处理来自于硬件端的包,另一方面需要处理来自于用户端的包,用户端包括web端和手机端等等.所以编写一个统一的CRC认证是非常必须要. 那么,在设计开始,CRC ...
- 物联网平台设计心得:管中窥豹之HeartBeat
前言 在写这篇文章之前,我曾对HeartBeat做过诸多的研究,也做过诸多的项目,在这些项目中,有客户端为了维持状态,而定时向服务端发送的HeartBeat:有服务端为了维持客户端连接状态而处理Hea ...
- 国内物联网平台(3):QQ物联智能硬件开放平台
国内物联网平台(3)——QQ物联·智能硬件开放平台 马智 平台定位 将QQ帐号体系.好友关系链.QQ消息通道及音视频服务等核心能力提供给可穿戴设备.智能家居.智能车载.传统硬件等领域的合作伙伴,实现用 ...
- 国内物联网平台(5):机智云IoT物联网云服务平台及智能硬件自助开发平台
国内物联网平台(5)——机智云IoT物联网云服务平台及智能硬件自助开发平台 马智 平台定位 机智云平台是致力于物联网.智能硬件云服务的开放平台.平台提供了从定义产品.设备端开发调试.应用开发.产测.运 ...
- 阿里云物联网平台体验(树莓派+Python篇)
阿里云物联网平台体验(树莓派+Python篇) 虽然对阿里云物联网平台比较熟悉了,从一开始就有幸参与了飞凤平台(Link Develop 一站式开发平台的前身)的一些偏硬件接入的工作.但是同时也见证了 ...
- 读懂SAP Leonardo物联网平台
读懂SAP Leonardo物联网平台 https://blog.csdn.net/weixin_42137700/article/details/81903290 本文比较系统.全面地介绍了SAP ...
- 国外物联网平台(8):Telit
国外物联网平台(8) ——Telit 马智 定位 We Bring IoT to Life Telit提供世界上最全面的高性能物联网模块.连接服务和软件. 产品体系 模块 Telit提供丰富专业的物联 ...
- 国外物联网平台(7):FogHorn
国外物联网平台(7) ——FogHorn 马智 引言: 据外媒在本月20日报道,硅谷初创公司FogHorn正在与谷歌合作以简化工业物联网应用的部署.本文对FogHorn的技术.产品.应用和生态进行了分 ...
- 国外物联网平台(6):Electric Imp
国外物联网平台(6)——Electric Imp 马智 公司背景 Electric Imp成立于2011年,公司设立在美国加利福尼亚州洛斯阿尔托斯和英国剑桥 公司投资者包括:富士康技术集团.PTI创投 ...
随机推荐
- hexo博客进阶-相册和独立域名
之前我已经写了一篇文章详细的讲述了如何使用hexo搭建github博客.如果还没有看的可以去看看,hexo搭建博客 其实,根据这篇文章的过程我们就能够搭建一个专属于自己,并且非常美观的博客了.但是如果 ...
- 使用hexo搭建属于自己的博客
如果你喜欢拥有自己的博客域名,如果你喜欢折腾,可以先点击luckykun.com,看看效果,再选择要不要进来看看--- 之前一直都在博客园写博客,不过最近在逛园子的时候不小心看到了hexo,简直有种相 ...
- Sharepoint学习笔记—习题系列--70-576习题解析 -(Q121-Q123)
Question 121 You are designing a SharePoint 2010 workflow that will be used to monitor invoices. Th ...
- SQL SERVER作业的Schedules浅析
SQL SERVER作业的计划(Schedules),如果你没仔细研究过或没有应用一些复杂的计划(Schedules),那么你觉得SQL SERVER作业的计划(Schedules)非常好用,也没啥问 ...
- MongoDB学习笔记~关于官方驱动集成IQueryable之后的一些事
回到目录 关于官方驱动集成IQueryable之后的一些事,有好事也有坏事,好事就是它会将你的linq语句非常友好的翻译成MongoDB语句,而坏事就是有一些linq语句不会被翻译,不会被翻译的代价就 ...
- x01.Weiqi.9: 点目功能
添加点目功能,虽不中,不远也.还是先看看截图吧. 确保其可行,再看一张: 其点目结果,还是比较令人满意的.这主要得益于多遍扫描,如编译器的词法分析阶段,下面的代码可以证明: private void ...
- 关于java中的MANIFEST.MF 文件内容
打开Java的JAR文件我们经常可以看到文件中包含着一个META-INF目录, 这个目录下会有一些文件,其中必有一个MANIFEST.MF,这个文件描述了该Jar文件的很多信息.可以简化Java应用程 ...
- 每建一个Activity都要注册权限Manifest.xml
每建一个Activity都要注册权限Manifest.xml 但是有时候自动注册好了,注意!不然的话是不能调用的!!!!!<activity android:name=".MainVi ...
- java设计模式之外观模式
外观模式概念 外观模式又称为门面模式,为子系统中的一组接口提供一个一致的界面,此模式定义了一个搞层次接口,使得这一个子系统更加容易使用.这一模式完美的体现了依赖倒转原则和迪米特法则的思想,所以是非常常 ...
- Java JDBC基础学习小结
JDBC是一个Java应用程序接口,作用是封装了对数据库的各种操作.JDBC由类和接口组成,使用Java开发数据库应用都需要4个主要的接口:Driver.Connection.Statement.Re ...