Posted on Saturday, August 19, 2023 Drag & Drop Interactive Grid rows Category APEX Tips and Tricks Here's an example that lets you drag and drop the rows of an interactive grid to arrange the records the way you want. A table used in an interactive grid must have a column that stores the sort order. If your table doesn't already have a column that can be used for this, edit the table and add a new column.alter table <your table name> add (display_seq number); update <your table name> set display_seq = rownum; alter table <your table name> modify display_seq not null;First, create an editable interactive grid and run the page. Sort the interactive grid in ascending order by display sequence column.Then hide the display sequence column from the report.Save the report.Create new column to the interactive grid .Enter a column name. Change the type to “HTML expression”. Add to the HTML Expression:<span aria-hidden="true" class="fa fa-sort z-sortable--handle"></span>Change the Source Type to None. Add a Column Initialization JavaScript Function:sortableIG.initHandleColumnEdit the other interactive grid columns and disable Sorting for all columns except the display sequence column.Edit the display sequence column and add a Column Initialization JavaScript Function:sortableIG.initSequenceColumnAdd to the interactive grid region Initialization JavaScript Function:sortableIG.initRegion Add to the page JavaScript Function and Global Variable Declaration:// create a namespace for sortable IG var sortableIG = {}; ( function( $, region, sortableIG ) { // Set defaults sortableIG.options = { region: { defaultModelOptions: { sequenceStep: 10 } ,defaultGridViewOptions: { reorderColumns: false } } ,handleColumn: { defaultGridColumnOptions: { noHeaderActivate: true } ,layout: { columnAlignment: "center" ,noStretch: true } } ,sequenceColumn: { features: { sort: true ,canHide: false ,aggregate: false ,compute: false ,controlBreak: false ,groupBy: false ,highlight: false ,pivot: false } } } // sortable IG handle column Initialization code // call function in IG column Advanced: Column JavaScript Initialization Code sortableIG.initHandleColumn = function( options ) { return $.extend( true, options, sortableIG.options.handleColumn ); } // sortable IG sequence column Initialization code // call function in IG column Advanced: Column JavaScript Initialization Code sortableIG.initSequenceColumn = function( options ) { // get sequence column name and store it for region Initialization JavaScript Function sortableIG.options.region.defaultModelOptions.sequenceField = options.name; return $.extend( true, options, sortableIG.options.sequenceColumn ); } // sortable IG initialization code // call function in IG region Advanced: JavaScript Initialization Code sortableIG.initRegion = function( options ) { $( $x( options.regionStaticId ) ).on( "interactivegridviewchange interactivegridreportsettingschange", function( _event, ui ) { var view = region( this.id ).call( "getViews", "grid" ) , sortableArea$ = $( $x( this.id ) ) , helperBgClass = "u-color-29-bg" ; // https://api.jqueryui.com/sortable/ sortableArea$.sortable({ handle: ".z-sortable--handle" ,items: "tr:has(.z-sortable--handle)" ,axis: "y" ,tolerance: "pointer" ,scrollSpeed: 8 ,placeholder: "a-GV-cell u-color-1-bg" ,helper: function( _event, ui ){ ui.children().each( function(){ $( this ).width( $( this ).width() ).addClass( helperBgClass ) }) return ui; } ,update: function( _event, ui ){ var model = view.model , item$ = $( ui.item ) // get moved record , item = ( item$.length ) ? model.getRecord( item$.data( "id" ) ) : null // get next or previous row from visible table depending is record moved up or down , after$ = ( ui.originalPosition.top > ui.position.top ) ? item$.next() : item$.prev() , after = ( after$.length ) ? model.getRecord( after$.data( "id" ) ) : null ; // remove helper background class, if row isn't actually moved item$.children().removeClass( helperBgClass ); // check if we have found record and place where record is moved if( item && after ){ // if record is moved upwards, we need get previous record from model after = ( ui.originalPosition.top > ui.position.top ) ? model.recordAt( model.indexOf( after ) - 1 ) : after; // move record if( item !== after ){ model.moveRecords( [item], null, after ); } } } }); }); return $.extend( true, options, sortableIG.options.region ); } })( apex.jQuery, apex.region, sortableIG );Add to the Page CSS Inline:.z-sortable--handle{ cursor: move; } .ui-sortable-helper{ display: inline-flex; }Now when you run a page, you can drag and drop to arrange the rows of the interactive grid from the handle column.See working example in apex.oracle.com.If you need support for touch events, you can try jQuery UI Touch Punch. Download jquery.ui.touch-punch.js and upload the file to Static Application Files. Reference the file e.g. on page JavaScript File URLs:#APP_FILES#jquery.ui.touch-punch.js