21

I am having a "small" issue with the angularjs ui datepicker. I need to indicate somehow, if an input with a datepicker attach, should show the popup from the bottom-left corner of the input (as default)

enter image description here

or if I want it from the bottom-right corner of the input instead. This is because in a page that I am creating, my input is really close to the right side of the page, and when I attach the datepicker, this happens (the datepicker is cutted and now a horizontal scroll appears):

enter image description here

but the thing is that I need the datepicker in both positions (according to the case related in the images).

Someone know how can this be fixed? I have tried changing the left attribute that is inline in the datepicker popup template, but it is always a fixed value and I believed that is not the real option.

Thanks

abottoni
  • 525
  • 1
  • 10
  • 19
  • 1
    Did you consider using CSS to add margins? It certainly seems like something is wrong with your CSS, probably because you are using a fixed layout. For instance, if your page has an absolute width of 1,000 px and your date-picker has a width of 300 px and has its `left` property at an absolute 800px then you are going to lose the rightmost 100px. It is generally a bad idea to have fixed layouts in CSS (what if the user re-sizes the browser, changes screen restitution, uses a mobile device with a smaller screen, etc?). This looks to me like a CSS problem and **not** and Angular problem. – Mawg says reinstate Monica Apr 22 '14 at 02:39
  • I have resolved this issue with a negative margin-left in CSS by adding a class to the parent tag of the datepicker. – stetro Jul 17 '14 at 13:35

5 Answers5

25

https://github.com/angular-ui/bootstrap/issues/1012

Ugly hack:

<div class="hackyhack">
  <input datepicker-popup="...">
</div>

Magic CSS:

.hackyhack {
  position: relative;
}
.hackyhack .dropdown-menu {
   left: auto !important;
   right: 0px;
 }
lincolnge
  • 1,037
  • 14
  • 19
7

Now latest angular-ui 1.2.0 onwards versions have popup-placement option in uib-datepicker-popup settings.

A quick summary from the docs.

popup-placement (Default: auto bottom-left, Config: 'placement') - Passing in 'auto' separated by a space before the placement will enable auto positioning, e.g: "auto bottom-left". The popup will attempt to position where it fits in the closest scrollable ancestor. Accepts:

top - popup on top, horizontally centered on input element.

top-left - popup on top, left edge aligned with input element left edge.

top-right - popup on top, right edge aligned with input element right edge.

bottom - popup on bottom, horizontally centered on input element.

bottom-left - popup on bottom, left edge aligned with input element left edge.

bottom-right - popup on bottom, right edge aligned with input element right edge.

left - popup on left, vertically centered on input element.

left-top - popup on left, top edge aligned with input element top edge.

left-bottom - popup on left, bottom edge aligned with input element bottom edge.

right - popup on right, vertically centered on input element.

right-top - popup on right, top edge aligned with input element top edge.

right-bottom - popup on right, bottom edge aligned with input element bottom edge.

In your case, I think bottom-right will work.

play with this plunker for more details.

vinesh
  • 4,745
  • 6
  • 41
  • 45
5

This CSS solution may be simpler than altering/hacking your angular .js files:

Wrap your datepicker in a div and then override the margin CSS of the datepicker's .dropdown-menu class:

<div id="adjust-left">
   <your-datepicker-here/>
<div>

Then, in the CSS:

#adjust-left .dropdown-menu{
    /* Original value: margin: 2px 0 0; */
    margin: 2px -Xpx; /* Where X is the amount of pixles to shift it left */
}
ForCripeSake
  • 73
  • 1
  • 4
  • 1
    Perfect solution! So simple. I added the attribute datepicker-postion-right to the datepicker. Then the css becomes: `input[datepicker-position-right] + ul { margin: 2px -Xpx;}`. No need for the extra div. – fizzyh2o Sep 29 '15 at 02:43
  • Good solution compared to other. – vinesh Mar 01 '16 at 11:49
3

Yeah I hacked my angular-ui.0.7.0.tpls.js file as described above and it worked pretty good:

function updatePosition() {
    scope.position = appendToBody ? $position.offset(element) : $position.position(element);
    scope.position.top = scope.position.top + element.prop('offsetHeight');

    var padding = 20; //min distance away from right side
    var width = popupEl.outerWidth(true);
    var widthOver =  $('body').outerWidth(true) - (scope.position.left + width + padding);

    if(widthOver < 0) {
        scope.position.left = scope.position.left + widthOver;
    }
}
John David Five
  • 811
  • 11
  • 15
  • Thanks for your solution, works very well. Only one thing to be corrected is popupEl.outerWidth(true) should be $(popupEl).outerWidth(true) – Kath Jan 04 '14 at 05:19
  • 3
    Urk!! When you have to hack something which is used by many then that has a Code Smell. Firstly, you will have to re-hack it every time the base code is updated, secondly, you are helping yourself, not others. Try approaching the owners of the code & ask them to change it so that others can influence it from outside. – Mawg says reinstate Monica Apr 22 '14 at 02:42
2

If you want to implement a general solution, this is something that cannot be achieved just by altering the template of the datepicker-popup.

You have to change the updatePosition function inside the directive, so that scope.position.left equals to something like this:

 scope.position.left += scope.position.width - $position.position(popupEl).width;

But again you have to be sure that you "read" the popuEl width after it is visible, otherwise you will get zero. Also, if you go to another mode (month or year selection) the position does not get updated although the popup width may change.

I just want to say that this feaure is not a one or two lines change, and probably it's better to open a request for this in https://github.com/angular-ui/bootstrap/issues?state=open Someone may be willing to investigate this further!

bekos
  • 1,303
  • 1
  • 13
  • 11
  • 2
    Hi Bekos. Thanks for your answer. I have opened the request and see if someone is willing to check this out. So far I have solved my problem but with a lot of changes. I had to alter the template and remove the left attribute from the inline style. The other thing that I did was encapsulate the input and the datepicker in a Div and using CSS and relative positioning I create a style for the left and right alignment and everywhere I used it, I set the CSS class according the alignment I need. – abottoni Sep 16 '13 at 07:13
  • 2
    I hope the guys of the bootstrap take this request in consideration because the workaround is just a weird way to handle this. Thanks for your help ! – abottoni Sep 16 '13 at 07:13
  • Yeah I hacked my angular-ui.0.7.0.tpls.js file as described above and it worked pretty good: – John David Five Nov 29 '13 at 04:52
  • It's not recommended to edit sources from your libraries. They might break when you update to a newer version – Fortin Oct 16 '20 at 20:09