This is a migrated thread and some comments may be shown as answers.

Persisting order changes for siblings

12 Answers 121 Views
TreeList
This is a migrated thread and some comments may be shown as answers.
Roger
Top achievements
Rank 2
Veteran
Roger asked on 27 Jan 2021, 04:27 AM

I have an application where the order of siblings under a node in the tree list is important and I would like to build upon the the demo at https://demos.telerik.com/kendo-ui/treelist/dragdrop whereby if I drag a node up or down within a branch, I can persist its order. 

In this example, if I drag Rinah above Akim in the list beneath Hyacinth, I would like to persist that order.  

 

I have been doing this fairly crudely by assigning an order field to each node - but figure there must be a better way.  Any suggestions?  

12 Answers, 1 is accepted

Sort by
0
Georgi
Telerik team
answered on 28 Jan 2021, 11:48 AM

Hi Roger,

Actually adding an order field is the suggested way to implement the described behavior.

Is there a use case which is not covered by this approach?

Another approach would be to cache the whole dataset as the treelist will reorder the data within the dataSource. However, caching the whole dataset might have a lot of side effects.

Regards,
Georgi
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Roger
Top achievements
Rank 2
Veteran
answered on 28 Jan 2021, 08:55 PM

Thanks Georgi - it's good to know that I have not entirely wasted my time using an Order field!  I guess that if I want to move a sibling in a 5 item branch to from position 4 to position 2, - either by using drag and drop or buttons on the side, I will have to do the following: (assuming that the order fields are numbered from 1 to 5)

  1. Determine the order number of The target field above which I am dropping the Moved Sibling (Field)
  2. Assign the Target Field Order to the Moved Field Order;
  3. Increment the Target Field Order and remaining fields beneath the target field by 1;

Are there any examples that you can point me to that implement this?  In my particular application, I am limiting my treelist to 3 levels - Week, Day, Item.  It is the items for which I want to change the order.  

Regards,

Roger

0
Roger
Top achievements
Rank 2
Veteran
answered on 01 Feb 2021, 06:03 AM

Hi Georgi:

I have built a sample app to illustrate my use case challenge at http://dojo.telerik.com/@rswetnam/AbIZOBIL/3

Building this has brought up some additional questions that I hoped you could help me with - or I can make another post if you prefer.

  1. What is the event that I would use as the entry to modify the the order values in the relevant rows in the in Day # 1 of the Week of Jan31, 2021 - e.g  moving 1 X220 metres after 2 X 100 metres?
  2. Is there a way that I can restrict the movement of these sets to the day in which they are created?  
  3. I would like to make all of the Day Nodes bold.  I have been partly able to do this at line 145 - but cannot get the value of the
    name
     in the string
    { field: "name", expandable: true, title: "Name", template: "#= level == 3 ? '<strong>name</strong>' : name#" },
  4. I want to be able to hide all buttons (Add, Edit and Delete) at the Program, Month and Week Levels (0, 1, 2), only allow Add and Edit buttons at the Day (Level 3) level and all buttons at the Set (Level 4) level.
  5. I would like to be able to style the buttons as links - as I have done for the Add Set links 

Any help on this would be greatly appreciated.

Roger

0
Accepted
Georgi
Telerik team
answered on 01 Feb 2021, 03:45 PM

Hi Roger,

Straight to your questions.

1. You could use the dragEnd event as it provides information for both destination and source. Within it, you could send a request to the server which will update the order field in the database. 

2. Unfortunately, the current implementation of the drag and drop does not support custom filters. At this point I can suggest you to submit a feature request to our feedback portal.

3. Configuring the template as shown below will display all day records in bold font:

                     { field: "name", expandable: true, title: "Name", template: "#= level == 3 ? '<strong>' +name + '</strong>' : name#" },

4. You could hide all commands which are not part of a day record within the dataBound event handler as shown below:

          dataBound: function(){
          	var that = this;
            
            that.tbody.find('tr').each(function(){
            	var row = $(this);
              var dataItem = that.dataItem(row);
              
              if(dataItem.level !== 3){
              	row.find('.k-button').hide()
              }
            })
          }

5. You could switch to a template column and instead of using the default commands which are button elements, create anchor tag buttons and handle their click events.

e.g.

// column

{template:"<a href='\\#' onclick='editRow(event)'>Edit</a>"}

// click handler

  function editRow(e){
    	var treelist =  $("#treeList").data("kendoTreeList");
      
      treelist.editRow($(e.target).parents('tr'))
    }

Regards,
Georgi
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Roger
Top achievements
Rank 2
Veteran
answered on 02 Feb 2021, 07:39 AM

Thanks so much for this Georgi - I have updated my demo project following your suggestions. 

I have two remaining issues that I am struggling with:

  1. How to get the value of dataItem.level here so that I can conditionally hide the fields for orders, reps and metres if the user has called the popup from the level of Day ? (line 62)
  2. For the 3 rows which show the up and down arrows, is there a way that I can determine if they are first in the series (1 X 220 metres) so that I can hide the up arrow, if they are last (6X30 metres) so that I can hide the last arrow or if they are the only set of the day so that I can hide both arrows?

Regards,

Roger

0
Georgi
Telerik team
answered on 03 Feb 2021, 11:59 AM

Hello Roger,

You can find more information about the kendo template syntax in the following article:

For example in your template you could conditionally display a span shown below:

<script id="popup_editor" type="text/html">
    #if(data.level === 3){#
      <span>level 3</span>
    #}#
  ...

As for conditionally hiding the up/down arrow buttons, you could do it within the dataBound event handler.

e.g.

            that.tbody.find('tr').each(function () {
                var row = $(this);
                var dataItem = that.dataItem(row);

                if (dataItem.name.indexOf('1 X') >= 0) {
                  row.find('[data-command="moveup"]').hide();
                }

                if (dataItem.name.indexOf('6 X') >= 0) {
                  row.find('[data-command="movedown"]').hide();
                }

For your convenience I have updated the provided dojo:

Regards,
Georgi
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Roger
Top achievements
Rank 2
Veteran
answered on 05 Feb 2021, 07:17 AM

Hi Georgi:

Thanks for your suggestions.  Regarding your first where you suggest how to conditionally display a span, 

<script id="popup_editor" type="text/html">
    #if(data.level === 3){#
      <span>level 3</span>
    #}#
  ...

my problem  is not so much on the display side as the getting the data on which to base the resolution of that condition.  In the case where I create a new child - add a new set, data.level is not in scope and I am not able to get a value.  

Also, I have run into one other issue that I am having a problem with.  When I add a new record, I increment the last order field by one.  I am trying to force a read at the end of the process so that the new record appears at the end of the list, not the top.  Do you have any suggestions there.

Thanks for all your help to date.

0
Roger
Top achievements
Rank 2
Veteran
answered on 05 Feb 2021, 07:18 AM
I forgot to mention that my updated sample project is at http://dojo.telerik.com/@rswetnam/AbIZOBIL/3
0
Georgi
Telerik team
answered on 08 Feb 2021, 02:10 PM

Hi Roger,

Within the edit template you have access to all fields of the edited model. However, when creating new item, all values have default values.

I can suggest you to use the internal _insertAt method of the treelist which accepts 2 parameters - the model and the index.

e.g.

treelist._insertAt({level: ..., ...}, calculatedIndex)

This way you can both assign a default value to the level field depending on the pressed button and insert the element at the index you want - in your case at the bottom.

Regards,
Georgi
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Roger
Top achievements
Rank 2
Veteran
answered on 11 Feb 2021, 08:01 AM

Thank you for this Georgi.  

I was unable to find an _insertAt for treeList in the documentation - though I was able to find one for the Wizard object.  As well, I have been having difficulty understanding where it should go in the code.  I have updated the code again at http://dojo.telerik.com/@rswetnam/AbIZOBIL/3 and believe that I have been able to solve the issue for having different fields open for different levels on editing.  I hope you can help me with the following questions 

  1. I believe that my edit function at line 247 sets out how the popup window to add or edit a record should be configured - but that the addNewRecord function at line 57 sets out how the data should be saved?  
  2. I believe that it is in this latter function where I should be putting the _insertAt function that you are referring to?
  3. I am not sure what the calculatedIndex is - or how I would calculate it here.  
  4. I would greatly appreciated it if you could show me how to get this working here or show me where I might find a demo on how the treelist._insertAt internal method is used.
  5. I am thinking that the insertAt method could also be used to help the ordering with the up and down buttons would be be useful here?  Any suggestions on how I might approach that would also be greatly appreciated.
  6. Pointing to any further tutorials or documentation related to some of the issues here on a more general level would be greatly appreciated.

Regards,

Roger

 

 

0
Accepted
Georgi
Telerik team
answered on 12 Feb 2021, 09:27 AM

Hi Roger,

The _insertAt method is internal and it is not part of the public API of the TreeList.

As requested I have updated the addNewRecord function:

   function addNewRecord(e) {
       var treelist = $('#treeList').data('kendoTreeList');
       var parent = treelist.dataItem($(e.target).parents('tr'));
       var parentId = parent[parent.idField];
       var newModel = {parentId: parentId, level: parent.level + 1};
       var index = treelist.dataSource._data.length - 1;
       var children;

       if (parent.hasChildren) {
           children = treelist.dataSource._data.filter(function (x) {
                return x[x.parentIdField] === parentId;
           });
           index = treelist.dataSource.indexOf(children[children.length - 1]) + 1;
       }

       treelist.expand(parent)
                    .then(function() {
                        treelist._insertAt(newModel, index);
                    });
    }

As for the reordering, the _insertAt method only inserts, thus, it is not suitable for the reordering as you will end up with duplicated items in the dataSource.

Nevertheless, you could instead use the insertAfter and insertBefore internal methods which accept 2 parameters, the moved element and the reference element.

e.g.

treelist.insertAfter(item, referenceItem) // this will remove the "item" from its current position and insert it after "referenceItem"

For your convenience I have updated the provided sample:

I hope this helps.

Regards,
Georgi
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Roger
Top achievements
Rank 2
Veteran
answered on 12 Feb 2021, 02:30 PM

Thanks Georgi - this was really helpful!

Regards,

Roger

Tags
TreeList
Asked by
Roger
Top achievements
Rank 2
Veteran
Answers by
Georgi
Telerik team
Roger
Top achievements
Rank 2
Veteran
Share this question
or