Kendo UI Reorderable Tabstrip Tabs

Posted by Meryk on 28-Oct-2015 12:52

Hello,

I am enabling the tabs on view pages, and want to make them reorderable.

I am using this exact code :

http://jsfiddle.net/6v8Su/12/

The only difference is that the tabs are already built in the page, so we are kind of rebuilding them when doing :

tabs = $('#tabs').kendoReorderableTabStrip().data('kendoReorderableTabStrip');

Also, some of  the tabs seem to be loading AJAX (when it is a grid I think).

It is working fine when I drag and drop but the sections under the tabs are not correct, ie, the sections are not following their tabs.

Firstly, is that a proper way to achieve this? because at the end the tabs are built twice ? 

And secondly, how do I correct this problem of sections not sitting under the right tab after Drag and Drop?

Thank you

Meryem

All Replies

Posted by Meryk on 30-Oct-2015 12:28

Hi guys,

Anything on this please?

I was thinking it is not very proper to use this method. Instead I am using Kendo Drag and Drop functionality to implement the Reordable.

Here is the code :

$(document).ready(function () {

var tabStrip = $('div[data-role="tabstrip"]').data('kendoTabStrip');

$('div[data-role="tabstrip"]').kendoDraggable({

group : 'tabs',
filter : '.k-item',
hint : function (e) {
return e.clone();
},
dragend : function (e) { 
var origin = e.initialTarget; //$(origin).text();
var target = e.toElement; //$(target).text();

var originTab = tabStrip.tabGroup.find(':contains("' + $(origin).text() + '")'); 
var originTabIndex = originTab.index(); 

var targetTab = tabStrip.tabGroup.find(':contains("' + $(target).text() + '")'); 
var targetTabIndex = targetTab.index(); 

//console.log(originTabIndex); console.log(targetTabIndex);

if(targetTabIndex > originTabIndex){
tabStrip.tabGroup.children('.k-item:eq(' + targetTabIndex + ')').after(tabStrip.tabGroup.children('.k-item:eq(' + originTabIndex + ')')); 
//tabStrip.element.children('.k-content:eq('+ targetTabIndex +')').after(tabStrip.element.children('.k-content:eq('+ originTabIndex +')') );
} 
else{ 
tabStrip.tabGroup.children('.k-item:eq(' + targetTabIndex + ')').before(tabStrip.tabGroup.children('.k-item:eq(' + originTabIndex + ')')); 
}
} 

});

$('div[data-role="tabstrip"]').kendoDropTarget({
group : 'tabs' 
});

});

This is dragging and dropping the Tabs fine but not the sections.

The issue is that I don't know how to link each section to its Tab, so when a tab moves the related section will always sit under it.

Any help ? The tabs are loading AJAX content as these sections are Grids of related objects. This is also the reason why a given section does not exist before clicking on a Tab.

How can we operate this shifting please?

Thank you

Meryem

Posted by Thierry Ciot on 30-Oct-2015 20:10

Did not have time to try your code but would like to understand:

Are you asking about how to create a reorderable tab strip custom kendo ui component?

Or are you asking how to use your custom component within Rollbase?

If the later, please could you post a sample RB application with the minimum amount of code and objects to reproduce the issue.  It will speed up how fast we can diagnose and provide an answer.  It will also minimize the chance that we mis-understand the problem.

thanks. Thierry.

Posted by Meryk on 02-Nov-2015 03:28

Hi Thierry,

I have no custom component really. I am just trying to make the Tabs Reorderable. Not sure if  the Rollbase Tabs (the one that comes up on the page when checking 'enable tabs') can be made Reorderable or if we need to build other custom tabs.

Basically, we don't want to build new tabs, we want to keep it user friendly by letting the user create his own tabs (using the design). If we build our own tabs we will lose this functionality and we would like to avoid that.

The code above is simply applying the kendo 'Drag and Drop' to the EXISTING tabs on the page.

Am I being clear? Please let me know if not as I need this feature to be implemented quickly.

Thank you

Meryem

Posted by Meryk on 04-Nov-2015 05:31

Hi guys,

Anything new on this please?

Thanks

Meryem

Posted by Mohammed Siraj on 05-Nov-2015 00:30

Meryem, in your solution you were not calling

 tabStrip._updateClasses(); , at the end of dragEnd function.

Once you do that .k-content div's are correctly tagged to Tab Item's.

However, for ajax loading tab contents we also keep track of tab index on server-side, hence, once you re-order tab's (which were not already  loaded), on selection they will load incorrect content.

To correct this behavior:

Disable ajax loading of tab-content i.e. tab content will be loaded at page  refresh & not on tab-selection. Note that this may degrade performance especially if you have many tabs on the page.

Else, make sure that each tab is selected/loaded atleast once before you enable re-ordering by making tabstrip draggable.

Posted by Mohammed Siraj on 05-Nov-2015 00:33

Also, un-comment second statement in IF block. Similar handling of .k-content div's  is required  in ELSE block for the 'PREVIOUS' case as done for 'AFTER' case:

if(targetTabIndex > originTabIndex){

tabStrip.tabGroup.children('.k-item:eq(' + targetTabIndex + ')').after(tabStrip.tabGroup.children('.k-item:eq(' + originTabIndex + ')'));

tabStrip.element.children('.k-content:eq('+ targetTabIndex +')').after(tabStrip.element.children('.k-content:eq('+ originTabIndex +')') );

}

else{

tabStrip.tabGroup.children('.k-item:eq(' + targetTabIndex + ')').before(tabStrip.tabGroup.children('.k-item:eq(' + originTabIndex + ')'));

}

tabStrip._updateClasses();

Posted by Mohammed Siraj on 05-Nov-2015 01:14

Final working solution, without 'Disabling Ajax Navigation', if a tab is not already loaded only in that scenario we will abort drag N drop, else tabs will be re-ordered accordingly.

<script>

 $(document).ready(function () {

var tabStrip = $('div[data-role="tabstrip"]').data('kendoTabStrip');

$('div[data-role="tabstrip"]').kendoDraggable({

group : 'tabs',

filter : '.k-item',

hint : function (e) {

return e.clone();

},

dragend : function (e) {

var origin = e.initialTarget; //$(origin).text();

var target = e.toElement; //$(target).text();

var originTab = tabStrip.tabGroup.find(':contains("' + $(origin).text() + '")');

var originTabIndex = originTab.index();

var targetTab = tabStrip.tabGroup.find(':contains("' + $(target).text() + '")');

var targetTabIndex = targetTab.index();

//do not go ahead with drag N drop if target tab is not loaded...  

if(!(originTab.data('rb-content-loaded') && targetTab.data('rb-content-loaded'))){

 console.log('Ensure target tab is loaded... aborting drag N drop');

 return;

}

//console.log(originTabIndex); console.log(targetTabIndex);

if(targetTabIndex >= originTabIndex){

tabStrip.tabGroup.children('.k-item:eq(' + targetTabIndex + ')').after(tabStrip.tabGroup.children('.k-item:eq(' + originTabIndex + ')'));

tabStrip.element.children('.k-content:eq('+ targetTabIndex +')').after(tabStrip.element.children('.k-content:eq('+ originTabIndex +')') );

}

else{

tabStrip.tabGroup.children('.k-item:eq(' + targetTabIndex + ')').before(tabStrip.tabGroup.children('.k-item:eq(' + originTabIndex + ')'));

tabStrip.element.children('.k-content:eq(' + targetTabIndex + ')').before(tabStrip.element.children('.k-content:eq(' + originTabIndex + ')'));

}

 tabStrip._updateClasses();

}

});

$('div[data-role="tabstrip"]').kendoDropTarget({

group : 'tabs'

});

});

 </script>

Posted by Meryk on 05-Nov-2015 04:00

Hi Siraj, Thanks for this. It is kind of working but still have a problem.

Let's say I have Tab1, Tab2 and Tab3, with associated div1, div2 and div3.

I first click on all the tabs to make sure the ajax content is loaded (I did the aborting thing but that is not ideal because how is the user going to guess that when trying to drag N drop?).

Now, I drag Tab1 and drop it after Tab3. Tab1 will be selected at this time with the right div under it. But if I go to something else and come back to click on Tab1, its content will be empty. Can you please let me know if you are having this same behavior, or if I am doing something wrong ?

My code is exactly the one above.

Thank you

Meryem

Posted by Mohammed Siraj on 05-Nov-2015 21:51

Am not seeing the same issue. it works well for me, if all tab contents are loaded (that is click each tab once).

Belevie that will happen if you are not calling  tabStrip._updateClasses(); at the end of dragEnd function. Can you please re-confirm?

Else, any change you are having another script component on the page that is playing spoilsport?

Posted by Meryk on 06-Nov-2015 06:47

Hi Siraj,

I am calling _updateClasses() at the end of dargend function.

Yes I might have some sort of spoilsport :)

Actually I am removing one of the Tabs before the drag and drop. This is probably what's messing with the reordering.

We actually need one of the content of these tabs out of tabstrip. so we need to copy its content above the tabs and remove the tab from tabstrip. Then work with the tabs normally, and drag and drop eventually..

Do you see what I am trying to do ? Otherwise, is there a way we could control where to add a tab on a page ? because now when we enable them, everything on a page is necessarily under a tab, which is exactly why we are struggling with all these manipulations.

Any suggestions on how to make this achievable in easier ways?

Thank you

Meryem

Posted by Meryk on 09-Nov-2015 08:01

Hello Siraj,

Have you had a chance to try this out please?

Thank you :)

Meryem

Posted by Mohammed Siraj on 12-Nov-2015 01:24

Meryem, can you try this change:

Call _updateClasses() on the tabstrip after you do the manipulation (similar to how we do it at the end of drag N drop) i.e.

"We actually need one of the content of these tabs out of tabstrip. so we need to copy its content above the tabs and remove the tab from tabstrip. Then work with the tabs normally, and drag and drop eventually.. "

See if this sets the class identifiers correctly so that the following drag N drop works smoothly.

Also, in the future release we are planning on a client - side SDK that will enable you to dynamically render page content. Hopefully that should help you with your requirement.

This thread is closed