[Sortable AF]  not working when navigating to current screen
Reactive icon
Forge component by Greg Whitten
Application Type

Hi all,

Found a scenario where the drag-and-drop sorting, using the forge component SortableAF, stops working when navigating to the current screen (it extends to other scenarios but this is the most direct and easy to explain) and would like to share the reason we found, and the solution applied. 

A - One screen with sortable tables or lists

A - When navigating to the current screen the sorting stops working until a refresh is made or navigation through another non-sortable screen (it would also work through other sortable screens but it would require a detail we explain below so let's leave it like this by now). We leave below the steps to replicate this scenario in the component demo.

Reason found:
- The reason seems to be that the component onDestroy event destroys the sortable object of the target screen instead of the source screen. This happens when the Id of the sortable widget is the same in the source and target screens. 
- The above happens on the "Getsortable" action that seems to catch the id of the target screen first (image below) 

- We noticed that the "el" field of the sortable object was losing its value on the target screen. Below is a console log in the OnReady action of the SortableAF component from the source screen and target screen respectively.

- An initial thought was to make sure the Ids were not the same but in the case of navigation to the current screen it would mean having dynamic Ids in some way so the approach changed to make sure to look for the correct object to destroy.
- The used solution was then to get the sortable object, still by Id, but through a selector that would identify the source screen (image below).

Steps to replicate scenario A

1- Created a link from the "Sortable" to itself
2- Opened the and sort is working
3- Clicked on the link and landed on the same screen
4- Tried to sort the lists and it did not work

The same behavior happens by doing the same above steps with the "SortableTable" to test on a table.

Also by copying a screen and navigating between the original and the copy it is possible to replicate. 

Real scenario

Our real scenario was an application that had a UI structure similar to some email boxes where on the left there is a list of items and on the right the details of the one we click. It is a screen with a sortable table and on the left, it has a web block with a sortable list.

We noticed the issue when we clicked on the left items and both the screen table and web block list stopped being sortable by the component from that point on until we refreshed the screen or navigated through non-sortable screens (it would also work if other screens were sortable but with different Ids but it was not our case). 

Also, the web block is used on another screen and we noticed it also stopped working when navigating directly between both screens that shared the web block.

On the screen, by navigating to itself the table name was the same, and so the target sortable object was being destroyed.

On the web block, no matter if the navigation was for the current screen or not, the Id of the list was the same and so the same happened and the target object was destroyed.


The above solution worked for us and everything seems to be working, so if you are reading this and have the same issue maybe it can also help you. For the component, it could be a good upgrade for the future to account for this scenario.

Hope this helps and feel free to reach out and give your feedback on this.

Fetching the element like this can lead to some issues such as when the OnDestroy is called for a reason other than navigation.

We can Improve this solution as follows:

  1.  Create a local variable SortableEl (type Object) on the block SortableList.
  2.  Inside the OnReady event of the block, store the Sortable element returned by the Create action on the SortableEl variable: 
  3. Replace the code inside the OnDestroy of the block with a JS to execute the destroy action on the stored object:

This approach guarantees that the element on which we are executing the destroy function is the same element that was created during the OnReady phase of this block, thus we no longer need to rely on finding the element by its id, and we no longer need to take into account if the element is inside the active screen container.

We could also store the destroy function inside a callback and execute it in the OnDestroy:

Best of luck and Happy Friday!


Community GuidelinesBe kind and respectful, give credit to the original source of content, and search for duplicates before posting.