I have a modal that appears and presents the user with a form. In this form are two Date Pickers. The problem is when I click one of the Date Picker form fields to select a date, the UI that appears for date selection is stuck within the constraints of the modal. Therefore, it gets cut off on the top and/or bottom depending on where in the modal I have scrolled. Moreover, the Date Picker UI is also cut off at the base line for the Date Picker form field.
Seeing as I have not done anything special in my modal or to the Date Picker, I believe this is an issue with how the Date Picker UI is being rendered within the modal.
Perhaps it should be reparented?
Please post your code.
<!-- Modal Structure -->
<div id="create-event" class="modal">
<div class="modal-content">
<div class="row">
<form class="col s12">
<div class="row">
<h4>Create a new event</h4>
</div>
<div class="row">
<div class="input-field col s6">
<input id="{{ event_form.title.id_for_label }}" type="text" class="validate">
<label for="{{ event_form.title.id_for_label }}">{{ event_form.title.label }}</label>
</div>
<div class="input-field col s6">
<input id="{{ event_form.host.id_for_label }}" type="text" class="validate">
<label for="{{ event_form.host.id_for_label }}">{{ event_form.host.label }}</label>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<input id="{{ event_form.menu_description.id_for_label }}" type="text" class="validate">
<label for="{{ event_form.menu_description.id_for_label }}">{{ event_form.menu_description.label }}</label>
</div>
<div class="input-field col s6">
<input id="{{ event_form.location_description.id_for_label }}" type="text" class="validate">
<label for="{{ event_form.location_description.id_for_label }}">{{ event_form.location_description.label }}</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<textarea id="{{ event_form.event_description.id_for_label }}" class="materialize-textarea validate"></textarea>
<label for="{{ event_form.event_description.id_for_label }}">{{ event_form.event_description.label }}</label>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<input id="{{ event_form.start_date.id_for_label }}" type="date" class="datepicker validate">
<label for="{{ event_form.start_date.id_for_label }}">{{ event_form.start_date.label }}</label>
</div>
<div class="input-field col s6">
<input id="{{ event_form.end_date.id_for_label }}" type="date" class="datepicker validate">
<label for="{{ event_form.end_date.id_for_label }}">{{ event_form.end_date.label }}</label>
</div>
</div>
</form>
</div>
</div>
<div class="modal-footer">
<div class="row center-align">
<a id="event-submit" class="btn waves-effect waves-light btn-large indigo lighten-3 col s11">Create Event</a>
</div>
</div>
</div>
This is because of how modals work, a fixed element within a fixed element will make it fixed within the other. Expanding the modal is the best solution.
The other is to take position absolute off .picker and position: absolute off .picker__holder and make .modal overflow: visible;
I tried both solutions. The latter did not work because the Date Picker would no longer appear when clicking the form field, likewise setting overflow: visible had undesirable effects on the modal.
Using the first solution, I was able to expand the modal and have the majority of the Date Picker appear. While not perfect, I may be able to work with this for large screens.
However, for small screens (in particular phones), the Date Picker is nearly unusable due to how it renders in the modal. Is there a way to get the Date Picker to work nicely on small screens? Perhaps, is there a way to scale down its size?
The datepicker modal should probably be attached to the document.body and not to the parent element of the field. That way it will have the entire display surface to show and not only the modal surface
I've run into this issue in my project, I have a modal with a form in it, and there's a datepicker field, when calendar opens up, it opens up inside of the modal. Looked at DOM and calendar gets generated inside of modal.
is there a fix out there for this?
The fix right now would be to have some js run to reparent the form to the body, don't know if this breaks the event handlers on the element.
@Dogfalo ok, i ran onRender() event to reattach it on body level
Hey Albert, can you explain better how did you solve the problem? When I tried to reparente the datepicker to the body using developer console it lost the event handlers when clicking on a date.
I have a big SaaS and I really need to use this datepicker inside modal. I already use datetimepicker bootstrap.
Can you help how did you solve?
[Edit]
The same thing happens with
@renanpontez here's what I've done in my case:
onStart: () => {
$('.picker').appendTo('body');
}
Thanks a lot Albert! Got it! Put on (...) picker.on('open') function (...).
:+1:
Hi,
Not sure what the fix is for this, can someone elaborate (@renanpontez)?
e.g. if the datepicker initialisation is
// datepicker
$('.datepicker').pickadate({
selectMonths: true, // Creates a dropdown to control month
selectYears: 15 // Creates a dropdown of 15 years to control year
});
what is the workaround? At the moment I have
$('.datepicker').on('open', function() {
$('.datepicker').appendTo('body');
});
but it didn't work (no errors).
@martincarlin87 I'll tell you what I did, ok? Not sure if it's the best idea to solve the problem but worked for me. Open "materialize.js " file and search for
// Bind some picker events.
picker.on (...)
So, at the end of the funtion picker.on('open') put this
picker.$root.find('button' + includeToday + ', select').attr('disabled', false)
$('.picker').appendTo('body');
},1).
Than, the Datepicker will be reparented to the body element.
Can you check if this is ok for you too?
Thank you @renanpontez for the amazingly quick reply.
I just tried this but it's still the same:
on( 'open', function() {
var includeToday = ''
if ( calendar.disabled( calendar.get('now') ) ) {
includeToday = ':not(.' + settings.klass.buttonToday + ')'
}
picker.$root.find( 'button' + includeToday + ', select' ).attr( 'disabled', false )
$('.datepicker').appendTo('body'); // I'm using 'datepicker' for the selector rather than 'picker'
}, 1 ).
I've also tried a couple of other things as the way I tried it above didn't seem right but neither has worked so far.
picker.appendTo('body');
picker.$root.appendTo('body');
EDIT
Ignore the above, I was editing the unminified version whilst using the minified version on my page...
This worked:
picker.$root.appendTo('body');
and was added after line 4762 in materialize.js
Great to hear you found the solution as well. :smile: @martincarlin87
Why just not use this? http://amsul.ca/pickadate.js/date/#container
juiced here:
$('.datepicker').pickadate({
container: 'body'
})
This works for me.
@brugnara I wasn't actually aware this option existed. In that case, this should fix the problem. Thanks for pointing that out!
Keep in mind that the pickadate.js guys also pointed out this:
When using this option, be careful not to set the container to something generic like the document鈥檚 body. This will break the document鈥檚 keyboard flow, for example when tabbing through a form. Instead, maintain the flow by keeping the container close to the input element.
I've used brugnara's post on attaching the datepicker to the container:body for a while. I just found this little css edit that seems to help.
@media screen and (min-height: 601px) {
.picker__holder {
overflow: visible !important;
}
}
The advantage for me is that the container fix has the disadvantage of being unable to use tab to skip through a form easily. This seems to be working for me.
Attaching the Date Picker to the body seems to have the unwanted side effect of causing the page to scroll to the bottom when the Date Picker is opened on Firefox or Internet Explorer. Does anyone know how to prevent this?
Here's an example of what I mean: http://codepen.io/awg/full/qZGNZo/
Update: For anyone else that runs into this problem. The way I solved it was to attach the Date Picker to an empty div instead of body and then add the following css:
#datepicker-container {
position: fixed;
z-index: 10000;
}
The z-index is the same as what the Date Picker's z-index is in my case.
@albertpak Thanks a lot man!!
@brugnara That's working great, man! Many thanks!
For me, simplest solution was to add style="overflow=visible;" to modal-body as per @Dogfalo comment.
datepicker-append-to-body="true" didn't help as it caused popup shown behind the modal.
Did anyone find a solution that still allows tabbing through the form?
$('.datepicker').pickadate({
container: 'body',
formatSubmit: 'yyyy-mm-dd'
})
This doesn't work as it puts the submit input element inside the date picker near the body which means it's outside of the form in the modal. Had to revert to just using the format option instead of formatSubmit
$('div[id$=date_root]').appendTo('body');
When I do
$('#date').datepicker({
container: 'body'
})
I'm having an error in the console:
Uncaught RangeError: Maximum call stack size exceeded.
at Modal._handleFocus (materialize.js?body=1:3004)
What to do?
@OnlyReFLeX does this error only appear on safari?
@mustii82 for everyone
Add the below code in your JS file and everything will be alright.
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.datepicker');
var instances = M.Datepicker.init(elems, { container: 'body' });
});
Most helpful comment
Why just not use this? http://amsul.ca/pickadate.js/date/#container
juiced here:
This works for me.