1、bootstrap栅格
超小屏幕 手机 (<768px) | 小屏幕 平板 (≥768px) | 中等屏幕 桌面显示器 (≥992px) | 大屏幕 大桌面显示器 (≥1200px) | |
---|---|---|---|---|
栅格系统行为 | 总是水平排列 | 开始是堆叠在一起的,当大于这些阈值时将变为水平排列C | ||
.container 最大宽度 | None (自动) | 750px | 970px | 1170px |
类前缀 | .col-xs- | .col-sm- | .col-md- | .col-lg- |
列(column)数 | 12 | |||
最大列(column)宽 | 自动 | ~62px | ~81px | ~97px |
槽(gutter)宽 | 30px (每列左右均有 15px) | |||
可嵌套 | 是 | |||
偏移(Offsets) | 是 | |||
列排序 | 是 |
使用单一的一组 .col-md-*
栅格类,就可以创建一个基本的栅格系统,在手机和平板设备上一开始是堆叠在一起的(超小屏幕到小屏幕这一范围),在桌面(中等)屏幕设备上变为水平排列。所有“列(column)必须放在 ” .row
内。
<div class="row">
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
</div>
<div class="row">
<div class="col-md-8">.col-md-8</div>
<div class="col-md-4">.col-md-4</div>
</div>
<div class="row">
<div class="col-md-4">.col-md-4</div>
<div class="col-md-4">.col-md-4</div>
<div class="col-md-4">.col-md-4</div>
</div>
<div class="row">
<div class="col-md-6">.col-md-6</div>
<div class="col-md-6">.col-md-6</div>
</div>
2、指令——验证输入框ip
angular.module('soc.app.pivot').directive('validateIpPort', function(){
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, ngModelCtrl){
function validator(input)
{
var regExp = /^((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])([:]\d{1,5})?)?$/;
var valid = regExp.test(input); //valid是个boolean
ngModelCtrl.$setValidity('ipPort', valid);//通过form的name.input的name.$error.ipPort判断
return valid ? input: ''; //ng-model的值会随着这个判断而改变
}
ngModelCtrl.$parsers.push(validator);//push里面放一个方法
}
};
});
这个ng-model里的变量会作为link的第四个参数 其实第四个参数是指向指令的控制器,而ngModal指令的控制器就是ng-modal双向绑定的值
$parsers这个属性和$setValidity()这个方法。 $parsers里保存了一组function, 每当DOM里数据变化的时候, 这组function会被一次调用。这里给了我们机会在用户修改了DOM里值的时候, 去对新输入的值做校验。
使用校验
<form class="form-horizontal" name="eventConfig">
<div class="col-md-3">
<input type="text" name="eventObject" class="form-control" validate-ip-port ng-model="event.eventObject"/>
</div>
<div class="addEventConfig-error-tips" role="alert" ng-show="eventConfig.eventObject.$dirty&&eventConfig.eventObject.$error.ipPort">
<i class="fa fa-times-circle"></i>
<span>ip地址格式错误</span>
</div>
eventConfig.eventObject.$error.ipPort 必须有form和input的name
3、验证输入框不能为空
input框要设置required属性
<div class="device-error-tips" role="alert" ng-show="addDeviceForm.devIp.$dirty&&addDeviceForm.devIp.$error.required">
<i class="fa fa-times-circle"></i>
<span>{{"error.tips.empty"|translate}}</span>
</div>
addDeviceForm.devIp.$dirty&&addDeviceForm.devIp.$error.required
4、指令——可以模糊查询的下拉列表
angular.module('soc.app.pivot').directive('eventName',['EventConfigService','serPNotify', function(EventConfigService,serPNotify){
'use strict';
return {
restrict: 'AE',
replace: true,
transclude : true,
scope: {
inputModal:'=',
},
template: '<div class="event-name-list">' +
'<input id="myInput" type="text" name="eventName" class="form-control" ng-model="inputModal" ng-change="changeInput()" autocomplete="off"/>'+
'<ul class="drop-menu" ng-show="eventNameShow">' +
'<li class="ruleName" ng-repeat="item in newEventNameList track by $index" ng-click="eventNameChange(item.ruleName)">' +
'{{item.ruleName}}' +
'</li></ul>' + '</div>',
link: eventNameLink
};
function eventNameLink(scope, element) {
scope.eventNameShow = false;
scope.newEventNameList=[];
scope.inputModal='-- 请选择 --';
/**
* 获取事件名称列表
*/
function getEventNameList() {
EventConfigService.getAllEventName().then(function (res) {
if (res && res.length) {
scope.eventNameList = res;
scope.eventNameList.unshift({ruleId:0,ruleName:'-- 请选择 --'});
angular.copy(scope.eventNameList,scope.newEventNameList);
scope.changeInput=function(){
if(scope.inputModal==''||scope.inputModal=='-- 请选择 --'){
scope.newEventNameList = angular.copy(scope.eventNameList);
}else{
scope.newEventNameList=[{ruleId:0,ruleName:'-- 请选择 --'}];
_.forEach(scope.eventNameList ,function(data,index,array){
if(data.ruleName.indexOf(scope.inputModal)>=0){
scope.newEventNameList.push(data);
}
});
}
};
}
}, function (res) {
serPNotify.error("获取事件名称失败");
});
}
getEventNameList();
scope.eventNameChange=function(ruleName){
scope.inputModal=ruleName;
};
var myDiv = document.getElementById("myInput");
document.addEventListener("click", function () {
scope.eventNameShow = false;
scope.$apply();//这个一定要加,否则隐藏不了
});
myDiv.addEventListener("click", function (event) {
scope.eventNameShow = true;
scope.$apply();
event = event || window.event;
event.stopPropagation();//阻止事件冒泡,防止隐藏
});
}
}]
);
scope:inputModal是为了双向绑定数据,指令中数据改变,控制器中数据也改变
可以不加scope:“inputModel:=” 因为不加的话指令的作用域和controller作用域是一个
但是这里面给的是$scope.event.eventName就会有问题 所以用inputModel代替eventModel
结构:一个div里面包着一个input框和一个ul,ul隐藏,里面的li的内容是动态获取过来的,把ul定为在input下面
动态获取ul中的内容,显示的内容为获取的数据深拷贝后的内容,因为要不影响原本获取的数据被改变
深拷贝:angular.copy(source, [destination]);
或者[destination]=angular.copy(source)
模糊查询:根据输入框输入的内容来查询ul列表中是否有含有输入的内容的数组,再把这些数组绑定给循环数组
这里不要用$watch,因为刚开始赋值input框内容为空的时候,它就会执行angular.$watch里面的内容
可以用input的ng-change事件(可以少用watch)
_.forEach(scope.eventNameList ,function(data,index,array){ if(data.ruleName.indexOf(scope.inputModal)>=0){ scope.newEventNameList.push(data); } });
判断获取的数组中是否含有输入的字段,用indexof进行判断,如果有就把这个数据添加进循环的数组
这里可以做一个事件防抖(加定时器,输入几秒以后再进行查询)
angular中的dom操作:
使用dom操作的原因:想要点击别的区域,下拉的ul隐藏,这个别的区域点击事件无法绑定在某个元素上,只能绑定在document上,所以就是document.addEventListener("click",function(){
隐藏,并且要加scope.$apply()脏检查,angular是自动会进行脏检查的,但是dom操作是不会的
})
此时如果给input框绑定ng-click事件是失效的,因为点击input框还是相当于点击dom
此时应该给input框一个dom操作让ul显示
双向绑定会失效:
- 当你的angular页面中引入了jq插件的时候,就可能会出现双向绑定失效的现象。
- 表现为你的变量打印出来是已经更改过的数值,但是页面中的数值不改变。应该是没有触发脏值检查,所以视图层不会更新。解决办法我们可以使用$scope.apply();
5、模态框
1、导入ui-bootstrap-tpls.js 这个是ui-bootstrap的库
2、angular.module('myModule', ['ui.bootstrap']); 模块中引入ui.bootstrap依赖(ui.bootstrap也是个模块)
3、然后在要使用的controller引入$uibModal服务
4、在要弹窗的地方:
var modalInstance = $uibModal.open({
templateUrl: '/soc/apps/pivot/html/modal/addEventConfigModal.html',
controller: 'addEventConfigController',
backdrop: 'static',
keyboard: false,
});
https://www.jianshu.com/p/2cbf835509b1 具体的文档
$uibModal.open({
animation: true,
templateUrl: '/soc/apps/pivot/html/modal/delete.html',
controller: 'deleteModalInstanceCtrl',
size:'sm'
}).result.then(function () { 点击确定之后
EventConfigService.deteleEventConfig(id).then(function(res){
serPNotify.success('删除成功');
getEventConfigList(); // 删除后重新获取列表
},function(res){ 点击取消之后
serPNotify.error('删除失败');
});
})
5、定义模态框的作用域controller,要引入依赖$uibModalInstance
有以下方法
名称 | 类型 | 含义 |
---|---|---|
close(result) | funcation | 关闭模态框,并传入结果 |
dismiss(reason) | funcation | 隐藏模态框,并传入原因 |
result | promise | 模态框已关闭 |
opened | promise | 模态框已打开,并加载完模板跟值 |
closed | promise | 模态框已关闭,且动画结束 |
rendered | promise | 模态框已渲染 |
angular.module('soc.app.pivot').controller('addEventConfigController',['$scope','$uibModalInstance','serPNotify','EventConfigService',function($scope,$uibModalInstance,serPNotify,EventConfigService){
$scope.chooseType='1';
$scope.addEvent={
addEventObject:'',
addEventName:'',
addEventSource:'',
addEventTarget:'',
}
$scope.create = function () {
if($scope.addEvent.addEventObject==''&&($scope.addEvent.addEventSource==''||$scope.addEvent.addEventTarget=='')){
serPNotify.error('请填入事件对象(不区分源/目标)+事件名称或事件来源+事件目标+事件名称');
}else{
if($scope.addEvent.addEventObject==undefined&&($scope.addEvent.addEventSource==undefined||$scope.addEvent.addEventTarget==undefined)){
serPNotify.error('请填入事件对象(不区分源/目标)+事件名称或事件来源+事件目标+事件名称');
}else{
if($scope.addEvent.addEventName=='-- 请选择 --'){
serPNotify.error('请选择事件名称');
}else{
EventConfigService.getAllEventName().then(function(res){
$scope.newEventNameList=res;
var eventName=_.find($scope.newEventNameList,{'ruleName':$scope.addEvent.addEventName})
var datas={
ip:$scope.addEvent.addEventObject,
ruleName:$scope.addEvent.addEventName,
ruleId:eventName.ruleId,
sip:$scope.addEvent.addEventSource,
dip:$scope.addEvent.addEventTarget
};
EventConfigService.createEventConfig(datas).then(
function(resp){
serPNotify.success("创建事件白名单成功");
$uibModalInstance.close();
window.location.reload();
},function(resp){
serPNotify.error("创建事件白名单失败");
}
)
});
}
}
}
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
}]);