I'm working on a single-screen application using Kendo for the UI. I just built in a datepicker on one of the screens, and it presented me with quite a strange behaviour.
Some background information: the application is single-screen, so I never navigate to different URLs, rather the content is changed by modifying the DOM with javascript. So I build up screens from scratch by creating the elements, and replacing $(body).html(), or any other parent I need to update if its a smaller change.
One of these screens has a DatePicker, created like this:
$(
"#captureDate"
).kendoDatePicker();
For the first time this screen loads, the DatePicker works fine. But if I navigate to another screen, and come back later, the DatePicker is loaded, but it's "frozen", meaning I can open it, it shows the right date, but none of the controls work inside the widget (changing the date/month/year etc.).
The #captureDate element is part of a kendo template rendered into the DOM every time this screen loads up (the element itself is an input with a date as the value, formatted with kendo.toString(), with culture set [to hu-HU]). The screens are "destroyed" on navigation by replacing the .html() of the changing element (usually the whole body) with the new screen's content.
What could be the cause of the problem? Thank you in advance for your help!
26 Answers, 1 is accepted
But if it helps, a bit of clarification to the error description: It's not just the datepicker on that particular page, but if I initialise a datepicker, then replace the content of the page via $(body).html() (thus deleting the animation containers and such elements from the DOM), no new datepicker instance will work from that point on (the datepickers will only function properly if the whole document is reloaded after this).
By the way, the jQuery UI datepicker had a similar error too, where if you deleted the container element, no datepicker instances could be displayed any more, but that problem was already solved by someone in the jQ community.
My solution is using http://keith-wood.name/datepick.html but i also wait for the fixed version of kendo.
Could you give me the solution for jQuery UI datepicker?
Here's the ticket on jQuery UI, and below in the Change History there are two solutions linked in from github. I used the last one: http://bugs.jqueryui.com/ticket/5679
wish you all the best!
Can KendoUI team give the comment on this issue?
Unfortunately the description of this issue is very vague so far. We need more details or a working demo showing what the problem is. We can't really comment anything right now.
Kind regards,Atanas Korchev
the Telerik team
Thanks for the quick answer, i am now creating the simple project to reproduce the issue.
Here you can find the possible reasons on that problem:
http://www.kendoui.com/forums/ui/general-discussions/method-for-removing-controls.aspx
The linked thread does not sound related to this issue. I guess providing a sample is the best way to proceed.
Greetings,Atanas Korchev
the Telerik team
sorry i was unclear. Actually i have same datePicker behavior, as it described here, but the steps i got it are described in the linked thread, because i was trying to remove the trailing divs with class named
k-animation-container
Anyway i got the example attached (VS 2010 ASP .NET MVC 3 with KendoUI).
Here is a short description on it (and two questions):
1. press "Load new DatePicker", open the datePicker dropdown
we can see then
<
div
class
=
"k-animation-container"
>...</
div
>
Press "Remove DatePicker" so it will remove datePicker with the div (k-animation-container).
Press "Load new DatePicker", to create datePicker second instance and open the datePicker dropDown. You can see it will have static content with unable to select the date in dropDown.
2. "Load new DatePicker", dont open the datePicker dropdown.
we will see at the end of the body:
<
div
style
=
"display: none; "
data-role
=
"calendar"
class
=
"k-widget k-calendar"
>...</
div
>
<
br
>
<
div
class
=
"k-calendar-container k-popup k-group k-reset"
data-role
=
"datepicker"
style
=
"display: none; position: absolute; "
></
div
><
br
>
There are two extra step required to remove the datepicker:
$("#datePicker").data('kendoDatePicker').dateView.popup.wrapper.remove();
$("#datePicker").data('kendoDatePicker').dateView.popup.element.remove();
$("#datePicker").removeData("kendoDatePicker");
This will remove one of the extra elements. The other can't really be removed because the DatePicker won't work without it - it is the shared calendar.
Atanas Korchev
the Telerik team
i will try it
I have tried the code snippet you mentioned, but it's same problem there.
I still able to reproduce the issue (remove and create again).
i am trying to get it worked, but no success yet :(
$('.k-animation-container').remove();
$('.k-reset').remove();
It appears that the k-reset class is only added to the appended containers at the bottom of the body. Can Atanas confirm this?
So far this appears to be working for my single page ajax driven site allowing the AutoComplete and DatePicker controls to still function properly.
Update: Actually just ran across an error with DatePicker not functioning doing that. AutoComplete still appears to be ok with that.
Update2:
<
script
src
=
"~/Scripts/kendo.datepicker.min.js"
type
=
"text/javascript"
></
script
>
What I would see prior to this was the popup would open but I couldn't select the header to change the depth or select a day. Only the Today in the footer would still be selectable. With the datepicker script getting returned on each request that has my datepicker included it appears to then be initializing properly the same as the initial load of the page.
any ideas on that problem?
The DatePicker widget uses shared calendar. When you need to dispose the DatePicker you need to move the shared calendar to the body or to remove it. Check this jsFiddle demo which shows how to achieve your goal.
Georgi Krustev
the Telerik team
Sorry, I missed the link to the demo. Here it is.
Yes it is better to not remove it. The demo shows how to dispose the DatePicker without removing the shared calendar.
Georgi Krustev
the Telerik team
thanks allot! you made my day ;)
your example works well for me, so the problem is totally solved now
Thank You!
function
cleanupControls() {
var
dp = kendo.ui.DatePicker.sharedCalendar.element.hide().detach();
$(
'.k-calendar'
).remove();
$(
'.k-animation-container'
).remove();
$(
'.k-reset'
).remove();
dp.appendTo(document.body);
}
This allows me to not have to do cleanup by specific control names and also no longer have to reference the external datepicker.js file.
And I too have a one page application which replaces various divs to construct the page on the fly.
Now my question is really why doesn't Kendo start the missing element/widget/... automatically when it needs it.
So .destroy() and create would work as in every other framework/programming language.
Or in other words: how to know what is missing and how to start it?
Br
Waldemar
... set global right click event... replace has(div) with your stuff.. I had a div as a top element in my context menu.
$(document).ready( function()
{
//Attach Kendo cleaner.
$( document ).on( "contextmenu", function()
{
//Remove all empty containers... from last to first.
var containers_empty: JQuery = $( ".k-animation-container:not(:has(div))" );
for ( var i: number = containers_empty.length - 1; i >= 0; --i )
{
containers_empty.get( i ).remove();
}
});
}
Br
Waldemar
The main issue (my fault) was that on popup destruction the inner data (kendoMenu) was not cleared.
So the working code is:
private static m_ContextMenu_Div =
'<div id="cm_svg_background">\
<ul class="k-context-menu">\
<li data-menuID="' + Enum_ContextMenu_ID.Value.Zone_Create + '"><span class="context_menu_item">Create Zone</span></li>\
<li data-menuID="' + + Enum_ContextMenu_ID.Value.Line_Create + '"><span class="context_menu_item">Create Line</span></li>\
</ul>\
</div>';
private Image_OnContextMenu = ( e: MouseEvent ): any =>
{
//Append div to body.
//
//Notice:
//As it's on the body location the kendoMenu will just wrap around the div and will not create a new one.
$( 'body' ).append( CShape_Background.m_ContextMenu_Div );
//Show context menu.
this.m_ContextMenu = $( "#cm_svg_background ul" ).kendoMenu(
{
orientation: "vertical",
select: ( selected: any ): void =>
{
//Close context menu.
this.Image_ContextMenu_Close();
//Inform parent.
this.m_Callback_ContextMenu( <Enum_ContextMenu_ID.Value>+( selected.item.dataset.menuid ) );
}
}).data( 'kendoMenu' );
//Get requested context menu.
this.m_ContextMenu_popUp = ( <any>$( "#cm_svg_background" ) ).kendoPopup(
{
//anchor: "#izs_svg",
anchor: "body",
animation: false,
collision: "fit flip"
}).data( "kendoPopup" );
//Register global OnClick event so that we'll be able to handle any out of menu clicks.
$( document ).on( "click", this.Image_ContextMenu_Close );
//Show context menu.
var coordinates = new Base.SCoortinates( e );
this.m_ContextMenu_popUp.open( coordinates.m_X, coordinates.m_Y );
//Do not show default context menu.
e.preventDefault();
}
private Image_ContextMenu_Close = (): any =>
{
//Close context menu.
if ( this.m_ContextMenu_popUp != null )
{
//Remove context menu.
this.m_ContextMenu.destroy();
this.m_ContextMenu = null;
//Close popup window.
this.m_ContextMenu_popUp.destroy();
this.m_ContextMenu_popUp = null;
//Remove page div.
$( '#cm_svg_background' ).remove();
}
//Remove global event.
$( document ).off( "click", this.Image_ContextMenu_Close );
}