7

I'm trying to use bootstrap datepicker (via angulart ui bootstrap) inside an ng-grid.

I'm setting the grid with:

$scope.gridSettings = {
    data: "myData",
    enableCellSelection: true,
    enableRowSelection: false,
    enableCellEditOnFocus: true,
    columnDefs:
        [
            { field: "StartDate", displayName: "Date", 
              editableCellTemplate: '<input type="text" datepicker-popup="dd/MM/yyyy" ng-model="COL_FIELD" />' }
        ]
};

And it works, when I click a cell it changes into a datepicker - but - the calendar popup is clipped by the cell boundaries - this means that I can only see the part of the popup that fits into the cell (the top border)

What do I need to set to allow the datepicker popup to appear above the grid instead of being clipped to the cell?

Update: tried switching from Angular UI bootstrap to angular-strap, now the datepicker works but I have the exact same problem with the timepicker

Nir
  • 29,306
  • 10
  • 67
  • 103

5 Answers5

8

Use datepicker-append-to-body=true

$scope.gridSettings = {
data: "myData",
enableCellSelection: true,
enableRowSelection: false,
enableCellEditOnFocus: true,
columnDefs:
    [
        { field: "StartDate", displayName: "Date", 
          editableCellTemplate: '<input type="text" datepicker-popup="dd/MM/yyyy" datepicker-append-to-body=true ng-model="COL_FIELD" />' }
    ]

};

lmyers
  • 2,654
  • 1
  • 24
  • 22
1

I actually had the same issue and eventually came up with this solution. Seems to be working well. The basic idea here is to hook on the datetimepicker show event (dp.show), detach it from wherever parent it may have, attach it to the body with position=absolute and set its location just below the target element.

Note that the below code is taken from a directive wrapping the bootstrap datetimepicker, however the same solution should apply anywhere as long as you can get a handle on the picker element.

Hope that helps someone :)

function link ($scope, $element, $attrs, ngModelCtrl) {

    ////////////////////////////////////////////////////////////////////////////////
    // the following code handles positioning of the datetimepicker widget
    // just below the target element. This is to avoid the hideous datepicker bug
    // that causes it to be trimmed when its parent has limited height
    // Z.P
    ////////////////////////////////////////////////////////////////////////////////
    $element.on('dp.show', function(e) {

        // get the datetimepciker
        var elem = angular.element('.bootstrap-datetimepicker-widget');

        // detach from parent element and append to body
        angular.element('body').append(elem);

        // get target element
        var target = e.currentTarget || e.delegateTarget || e.target;

        // get bounding rects of parent and element
        var targetRect = angular.element(target)[0].getBoundingClientRect();
        var elemRect = elem[0].getBoundingClientRect();

        // do some math
        var marginTop = 10;
        var center = targetRect.left + (targetRect.width / 2) - (elemRect.width / 2);
        var top = targetRect.bottom + marginTop;

        // position the widget properly just below parent
        elem.css('position', 'absolute');
        elem.css('z-index', '10000000000000');
        elem.css('top', top + 'px');
        elem.css('bottom', 'auto');
        elem.css('left', center + 'px');
    });
}
Zacky Pickholz
  • 1,106
  • 9
  • 10
0

Go into the ng-grid.css file and comment out the following:

.ngCell {
  /*overflow: hidden;*/
  position: absolute;
  top: 0;
  bottom: 0;
  background-color: inherit;
}

This has worked for me for displaying validation messages and for my application I have seen no side effects.

Rob
  • 2,721
  • 1
  • 20
  • 27
  • This makes an horizontal scrollbar cover the last row of the grid and the timepicker popup (see update in the question why timepicker and not datepicker) is still clipped by the cell – Nir Jan 09 '14 at 07:39
0

Use the following cellTemplate for the cell where you want to add a datepicker. :

 dateCellTemplateEdit = '<div class="controls input-append"><input id="valueDt{{row.rowIndex}}" class="datepicker" type="date" value="{{row.entity.valuedtstr}}" style ="font-size:13px; width:60%; " data-date-format="mm-dd-yyyy"  ng-model="row.entity.valuedtstr" readOnly="true"  /><div class="add-on"><i class="icon-calendar" ></i><div>';
0

Replace the ng-input in the editableCellTemplate with your own directive.

Plunker

the critical point in that directive is the ngGridEventEndCellEdit. Instead of emitting it "onBlur", you emit it when datepicker's isOpen is set to false:

            scope.isOpen = true;

            scope.$watch('isOpen', function (newValue, oldValue) {
                if (newValue == false) {
                    scope.$emit('ngGridEventEndCellEdit');
                }
            });

            angular.element(elm).bind('blur', function () {
                //scope.$emit('ngGridEventEndCellEdit');
            });

The according editableCellTemplate (note my-input instead of ng-input):

 '<input ng-class="\'colt\' + col.index" datepicker-popup="dd.MM.yyyy" datepicker-append-to-body=true is-open="isOpen" ng-model="COL_FIELD" my-input="COL_FIELD"/>';
renegone
  • 11
  • 6