我在ui-grid中使用AngularJS Bootstrap datepicker(3.0.0 - 不稳定)
我已经通过自定义cellTemplate(ui-grid)实现了datepicker:
{
field: 'Wiedervorl',
displayName: 'Wiedervorl.',
enableCellEdit: true,
enableCellEditOnFocus: true,
enableHiding: false,
cellTemplate: '<div><input ng-model="row.entity.Wiedervorl" ng-change="grid.appScope.addModifyFlag(row.entity)" ng-click="opened = true;" datepicker-popup="dd.MM.yyyy" is-open="opened" datepicker-options="grid.appScope.dateOptions" datepicker-append-to-body="true" type="text" /></div>',
cellFilter: 'date',
cellClass: function () {
return 'text-left';
},
filter: {
placeholder: 'date',
condition: uiGridConstants.filter.CONTAINS
},
width: '7%'
},
在datepicker输入中有一个标记'open',它与该输入元素的一个实例(datepicker实例)完全隔离。
问题是,在另一行中再打开一个日期选择器之后,前一个没有关闭,并且可以同时打开多个日期选择器。
我尝试在输入中添加“ng-blur”,但是当datepicker打开时,它会执行。
任何想法,如何在UI-Grid中完成之前的datepicker实例的关闭?一次只能激活一个。
由于
答案 0 :(得分:8)
也许这对某人有帮助。我对如何将Bootstrap执行器集成到UI网格进行了详细调查。
首先,您需要使用自定义editableCellTemplate
和自定义指令,以正确处理END_EDIT
和CANCEL_EDIT
事件。
您可以在下面找到我的指令代码:
var app = angular.module('ui.grid.edit');
app.directive('uiGridEditDatepicker', ['$timeout', '$document', 'uiGridConstants', 'uiGridEditConstants', function($timeout, $document, uiGridConstants, uiGridEditConstants) {
return {
template: function(element, attrs) {
var html = '<div class="datepicker-wrapper" ><input uib-datepicker-popup is-open="isOpen" ng-model="' + attrs.rowField + '" ng-change="changeDate($event)" on-open-focus="false" disabled/></div>';
return html;
},
require: ['?^uiGrid', '?^uiGridRenderContainer'],
scope: true,
compile: function() {
return {
pre: function($scope, $elm, $attrs) {
},
post: function($scope, $elm, $attrs, controllers) {
var setCorrectPosition = function() {
var gridElement = $('.ui-grid-viewport');
var gridPosition = {
width: gridElement.outerWidth(),
height: gridElement.outerHeight(),
offset: gridElement.offset()
};
var cellElement = $($elm);
var cellPosition = {
width: cellElement.outerWidth(),
height: cellElement.outerHeight(),
offset: cellElement.offset()
};
var datepickerElement = $('ul', cellElement);
var datepickerPosition = {
width: datepickerElement.outerWidth(),
height: datepickerElement.outerHeight()
};
var newOffsetValues = {};
var isFreeOnRight = (gridPosition.width - (cellPosition.offset.left - gridPosition.offset.left) - cellPosition.width) > datepickerPosition.width;
if (isFreeOnRight) {
newOffsetValues.left = cellPosition.offset.left + cellPosition.width;
} else {
newOffsetValues.left = cellPosition.offset.left - datepickerPosition.width;
}
var freePixelsOnBottom = gridPosition.height - (cellPosition.offset.top - gridPosition.offset.top) - cellPosition.height;
var freePixelsOnTop = gridPosition.height - freePixelsOnBottom - cellPosition.height;
var requiredPixels = (datepickerPosition.height - cellPosition.height) / 2;
if (freePixelsOnBottom >= requiredPixels && freePixelsOnTop >= requiredPixels) {
newOffsetValues.top = cellPosition.offset.top - requiredPixels + 10;
} else if (freePixelsOnBottom >= requiredPixels && freePixelsOnTop < requiredPixels) {
newOffsetValues.top = cellPosition.offset.top - freePixelsOnTop + 10;
} else {
newOffsetValues.top = gridPosition.height - datepickerPosition.height + gridPosition.offset.top - 20;
}
datepickerElement.offset(newOffsetValues);
datepickerElement.css("visibility", "visible");
};
$timeout(function() {
setCorrectPosition();
}, 0);
$scope.isOpen = true;
var uiGridCtrl = controllers[0];
var renderContainerCtrl = controllers[1];
var onWindowClick = function (evt) {
var classNamed = angular.element(evt.target).attr('class');
var inDatepicker = (classNamed.indexOf('datepicker-calendar') > -1);
if (!inDatepicker && evt.target.nodeName !== "INPUT") {
$scope.stopEdit(evt);
}
};
var onCellClick = function (evt) {
console.log('click')
angular.element(document.querySelectorAll('.ui-grid-cell-contents')).off('click', onCellClick);
$scope.stopEdit(evt);
};
$scope.changeDate = function (evt) {
$scope.stopEdit(evt);
};
$scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {
if (uiGridCtrl.grid.api.cellNav) {
uiGridCtrl.grid.api.cellNav.on.navigate($scope, function (newRowCol, oldRowCol) {
$scope.stopEdit();
});
} else {
angular.element(document.querySelectorAll('.ui-grid-cell-contents')).on('click', onCellClick);
}
angular.element(window).on('click', onWindowClick);
});
$scope.$on('$destroy', function () {
angular.element(window).off('click', onWindowClick);
});
$scope.stopEdit = function(evt) {
$scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
};
$elm.on('keydown', function(evt) {
switch (evt.keyCode) {
case uiGridConstants.keymap.ESC:
evt.stopPropagation();
$scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
break;
}
if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;
if (uiGridCtrl.cellNav.handleKeyDown(evt) !== null) {
$scope.stopEdit(evt);
}
} else {
switch (evt.keyCode) {
case uiGridConstants.keymap.ENTER:
case uiGridConstants.keymap.TAB:
evt.stopPropagation();
evt.preventDefault();
$scope.stopEdit(evt);
break;
}
}
return true;
});
}
};
}
};
}]);
注意!我的指令要求jQuery在网格中设置datepicker的正确位置。如果您不使用jQuery,则应该在指令中注释调用setCorrectPosition()
。在这种情况下,datepicker将根据标准行为放置在网格中。
您可以在Github上找到有关如何使用它和示例代码的一些额外信息:https://github.com/Joiler/ui-grid-edit-datepicker
答案 1 :(得分:4)
如果有人像我一样遇到过这种情况,ui-grid也已经拥有了它自己的内置日期选择器选项。
$scope.gridOptions.columnDefs = [
{ name: 'registered',
displayName: 'Registered',
type: 'date',
cellFilter:'date:"yyyy-MM-dd"'}
];
除非像OP那样需要特定类型的外部日期选择器,否则这看起来非常方便且易于使用。
答案 2 :(得分:2)
您需要在其中实现带有日期选择器的指令,该指令需要向网格提供END_EDIT和CANCEL_EDIT事件。请参阅编辑教程:http://ui-grid.info/docs/#/tutorial/201_editable(就在ColumnDef选项之上)。
您可以在https://github.com/angular-ui/ng-grid/blob/master/src/features/edit/js/gridEdit.js中看到与下拉指令相关联的代码,从底部开始的第二个块
答案 3 :(得分:0)
app.directive('uiGridEditDatepicker', ['$timeout', '$document', 'uiGridConstants', 'uiGridEditConstants', function($timeout, $document, uiGridConstants, uiGridEditConstants) {
return {
template: function(element, attrs) {
var html = '<div class="datepicker-wrapper" ><input type="text" uib-datepicker-popup datepicker-append-to-body="true" is-open="isOpen" ng-model="datePickerValue" ng-change="changeDate($event)" popup-placement="auto top"/></div>';
return html;
},
require: ['?^uiGrid', '?^uiGridRenderContainer'],
scope: true,
compile: function() {
return {
pre: function($scope, $elm, $attrs) {
},
post: function($scope, $elm, $attrs, controllers) {
$scope.datePickerValue = new Date($scope.row.entity[$scope.col.field]);
$scope.isOpen = true;
var uiGridCtrl = controllers[0];
var renderContainerCtrl = controllers[1];
var onWindowClick = function (evt) {
var classNamed = angular.element(evt.target).attr('class');
if (classNamed) {
var inDatepicker = (classNamed.indexOf('datepicker-calendar') > -1);
if (!inDatepicker && evt.target.nodeName !== "INPUT") {
$scope.stopEdit(evt);
}
}
else {
$scope.stopEdit(evt);
}
};
var onCellClick = function (evt) {
angular.element(document.querySelectorAll('.ui-grid-cell-contents')).off('click', onCellClick);
$scope.stopEdit(evt);
};
$scope.changeDate = function (evt) {
$scope.row.entity[$scope.col.field] = $scope.datePickerValue;
$scope.stopEdit(evt);
};
$scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {
if (uiGridCtrl.grid.api.cellNav) {
uiGridCtrl.grid.api.cellNav.on.navigate($scope, function (newRowCol, oldRowCol) {
$scope.stopEdit();
});
} else {
angular.element(document.querySelectorAll('.ui-grid-cell-contents')).on('click', onCellClick);
}
angular.element(window).on('click', onWindowClick);
});
$scope.$on('$destroy', function () {
angular.element(window).off('click', onWindowClick);
//$('body > .dropdown-menu, body > div > .dropdown-menu').remove();
});
$scope.stopEdit = function(evt) {
$scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
};
$elm.on('keydown', function(evt) {
switch (evt.keyCode) {
case uiGridConstants.keymap.ESC:
evt.stopPropagation();
$scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
break;
}
if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;
if (uiGridCtrl.cellNav.handleKeyDown(evt) !== null) {
$scope.stopEdit(evt);
}
} else {
switch (evt.keyCode) {
case uiGridConstants.keymap.ENTER:
case uiGridConstants.keymap.TAB:
evt.stopPropagation();
evt.preventDefault();
$scope.stopEdit(evt);
break;
}
}
return true;
});
}
};
}
};
}]);