Is there an easy way to DragReorderRows in Web App?

I’m using a WebListBox and would like to give the user the ability to move a row up/down and reorder the rows. The WebListBox contains a list of ‘steps’, and rather than force the user to delete and re-add steps in order to put them in the right sequence it seems more intuitive to allow a dragging of rows to change their order. It seems that the Desktop version of ListBox has this feature - is there any similar functionality in Web?

I don’t think it’s possible.
I did it but using the websdk, and building a bootstrap table, some javascript to drag the rows
I needed it a year ago and I didn’t figure how to do it with the weblistbox at the time.
they need to add this feature to the xojo web framework though…

It seems to be missing the dragReorderRows event and other drag-related ones.

Checking back over my issues history from 3 years ago it was in the test version but was removed before release, probably due to numerous bugs being found late in its implementation even though it was scheduled to be used in the “new feedback system” which would have needed that functionality.

I couldn’t find a way to do it in a web app, so added a up/down arrows to move the selected rows:

GraffitiGrid for Web supports row reordering.

3 Likes

Hi Anthony, thanks for the reminder! I think it’s time I stop making such ugly web apps and get on board with your elegant Graffiti Suite :+1:t2:

1 Like

Okay, for now I’ll consider it “can’t be done easily or with WebList functionality” and tackle it with Graffiti or array manipulation. Thanks everyone!

@David_Cox Hi David. I’ve been struggling (failing) to do something very similar to your solution. I need rows with the word “FEE” in them to be reordered to the end of the list (looping through all rows, using instr on column 0 to get the column’s text). Would a variation of what you’ve done here work for that? If so, would you mind sharing how you accomplished the reorder?

Sorry I meant “I’ve been looping through all rows, using instr on column 0 to get the column’s text”.

Here is my solution. I use it for Desktop and Web, ListBox and GraffitiGrids, so you can remove the code that is redundant to your requirements.

Note that I use CommonWindow.getCurrentlySelectedRowsWAD to get an array of those rows that are currently selected, then restore them with CommonWindow.doRestoreSelectedRowsWAD, so you can keep pressing the Up/Down arrow keys to move them again.

Other Methods (like getListBoxSelectedRowIndex, getListBoxRowTag, getListBoxCellValueAt, doListBoxSelectedRowIndex and isListBoxRowSelected) can be returned to their simpler functions. I use them so I can use Desktop/Web/Mobile list code without modification.

Protected Sub doMoveListBoxRowsUpDown(myListBox As Object, isMoveUp As Boolean = True)
  'moves the selected items in the provided ListBox up or down
  If myListBox = Nil Then Return
  
  #If TargetDesktop Then
    Var tempListBox As DesktopListbox = DesktopListbox(myListBox)
  #ElseIf TargetWeb Then
    Var tempListBox As GraffitiGrid = GraffitiGrid(myListBox)
  #EndIf
  
  #If TargetDesktop Or TargetWeb Then 'Web 2.0 not compatible with Selected yet, but GraffitiGrid is. Not Console!
    Var currentlySelected() As Variant = CommonWindow.getCurrentlySelectedRowsWAD(tempListBox)
    Var isSelected As Boolean = False 'Web API 2.0 cannot handle RowSelectedAt()
    
    'Move the selected fields down
    If CommonWindow.getListBoxSelectedRowIndex(tempListBox) < 0 Then Return 'no rows or nothing selected!
    isSelected = CommonWindow.isListBoxRowSelected(tempListBox, 0)
    If isMoveUp And isSelected Then Return 'cannot move selection higher than the top!
    isSelected = CommonWindow.isListBoxRowSelected(tempListBox, CommonWindow.getListBoxRowCount(tempListBox) - 1)
    If Not isMoveUp And isSelected Then Return 'cannot move selection lower than the bottom!
    
    If isMoveUp Then 'up arrow
      For tempInt As Integer = 1 To tempListBox.RowCount - 1
        isSelected = CommonWindow.isListBoxRowSelected(tempListBox, tempInt)
        If isSelected Then 'swap the table rows!
          Var tempCellRowTag1 As Variant = CommonWindow.getListBoxRowTag(tempListBox, tempInt)
          Var tempCellRowTag2 As Variant = CommonWindow.getListBoxRowTag(tempListBox, tempInt - 1)
          
          For tempInt2 As Integer = 0 To tempListBox.ColumnCount - 1 'swap the columns within the rows!
            Var tempCellValueAt1 As String = CommonWindow.getListBoxCellValueAt(tempListBox, tempInt, tempInt2)
            Var tempCellValueAt2 As String = CommonWindow.getListBoxCellValueAt(tempListBox, tempInt - 1, tempInt2)
            
            CommonWindow.doListBoxCellValueAt(tempListBox, tempInt, tempInt2, tempCellValueAt2)
            CommonWindow.doListBoxCellValueAt(tempListBox, tempInt - 1, tempInt2, tempCellValueAt1)
          Next
          CommonWindow.doListBoxSelectedRowIndex(tempListBox, tempInt - 1, True)
          CommonWindow.doListBoxSelectedRowIndex(tempListBox, tempInt, False)
          
          CommonWindow.doListBoxRowTagAt(tempListBox, tempInt, tempCellRowTag2)
          CommonWindow.doListBoxRowTagAt(tempListBox, tempInt - 1, tempCellRowTag1)
        End If
      Next
      
    Else 'down arrow
      For tempInt As Integer = tempListBox.RowCount - 2 DownTo 0
        isSelected = CommonWindow.isListBoxRowSelected(tempListBox, tempInt)
        If isSelected Then 'swap the table rows!
          Var tempCellRowTag1 As Variant = CommonWindow.getListBoxRowTag(tempListBox, tempInt)
          Var tempCellRowTag2 As Variant = CommonWindow.getListBoxRowTag(tempListBox, tempInt + 1)
          
          For tempInt2 As Integer = 0 To tempListBox.ColumnCount - 1 'swap the columns within the rows!
            Var tempCellValueAt1 As String = CommonWindow.getListBoxCellValueAt(tempListBox, tempInt, tempInt2)
            Var tempCellValueAt2 As String = CommonWindow.getListBoxCellValueAt(tempListBox, tempInt + 1, tempInt2)
            
            CommonWindow.doListBoxCellValueAt(tempListBox, tempInt, tempInt2, tempCellValueAt2)
            CommonWindow.doListBoxCellValueAt(tempListBox, tempInt + 1, tempInt2, tempCellValueAt1)
          Next
          CommonWindow.doListBoxSelectedRowIndex(tempListBox, tempInt + 1, True)
          CommonWindow.doListBoxSelectedRowIndex(tempListBox, tempInt, False)
          
          CommonWindow.doListBoxRowTagAt(tempListBox, tempInt, tempCellRowTag2)
          CommonWindow.doListBoxRowTagAt(tempListBox, tempInt + 1, tempCellRowTag1)
        End If
      Next
    End If
    
    CommonWindow.doRestoreSelectedRowsWAD(tempListBox, currentlySelected)
    
    #If TargetWeb Then
      tempListBox.UpdateDisplay
    #EndIf
  #EndIf
      
End Sub

Thank you, David! Looks like CommonWindow code is specific to GraffitiGrids? I assume so, because I’ve never heard of that before or seen it in any Xojo docs. Sadly, GraffitiGrids is beyond my financial means. I greatly appreciate your response nonetheless. :slight_smile:

Unfortunately my Method cannot be simply transported, but hopefully you can see the flow of the logic and use that. Yes, remove all code referencing GraffitiGrids!

I’ll see what I can do! Thanks again.