Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Possible bug? Tableview index not updating after deleteRows
Started by J@V0 Jan 02 2019 11:30 AM

- - - - -
7 replies to this topic
tableview

Best Answer anaqim , 02 January 2019 - 01:00 PM

oh yes you can.

 

in the OnRowTouch function you use event.target, which points to the row itself, instead of event.target.index which is just the stored index from when the tableview was created.

 

i think my requery and rebuild statement is colored by how my app handle it.

 

i have a query function that pulls data from a sql server and stores it in an array.

after each query, i delete all rows and run a tableView:insertRow loop to repopulate the tableView.

 

how you get the source data used to populate the tableView may differ but the process should be close to identical.

[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

J@V0

[GLOBAL: userInfoPane.html]
J@V0
  • Enthusiast

  • 43 posts
  • Corona SDK

I'm having an issue with a Tableview where the ID of the rows doesn't get updated after a row has been deleted with deleteRows. I've tried to reload the table but it does not help. It seems someone else had the issue a couple of years ago and it doesn't seem to be fixed?

 

Below you can find a full working example showing the problem. Sorry I couldn't make it smaller.

local composer = require( "composer" )
local scene = composer.newScene()
local widget = require "widget"
local globalData = require( "globalData" )

local tableView
local deleteButton

local function confirmDeleteFile( event )
    if ( event.action == "clicked" ) then
      local i = event.index
      if ( i == 1 ) then
        local result, reason = os.remove( system.pathForFile( globalData.fileTapped, system.DocumentsDirectory ) )
         tableView:deleteRows( { globalData.rowIndexTapped } )
         tableView:reloadData()
      end
      return true -- indicates successful touch
    end
end

local function onDeleteButtonRelease(event)
  local alert = native.showAlert( "Delete saved game", "Are you sure you want to delete this game?", { "Yes", "No, cancel" }, confirmDeleteFile )
  return true -- indicates successful touch
end

local function onRowTouch(event)
    print("onRowTouch (event.target.index): "..event.target.index)
    local row = event.target
  
    if ( event.phase == "release" or event.phase == "tap" ) then
      globalData.fileTapped = event.target.params.file
      globalData.rowIndexTapped = event.target.index
      
      deleteButton:addEventListener("tap", onDeleteButtonRelease)
      
      for i = 1, tableView:getNumRows() do    
        if i == row.index then
          tableView._view._rows[i]._rowColor.default = { 1, 100/255, 100/255 }
        else
          local indexVisibleLine = tableView:getRowAtIndex( i ) -- This makes sure the line is visible. If not visible, _view._rows[i] will crash
          if ( indexVisibleLine ) then
            tableView._view._rows[i]._rowColor.default = { 232/255, 232/255, 232/255 }
          end
        end
      end
      tableView:reloadData()  
      return true -- indicates successful touch      
    end
end


function scene:create( event )
local sceneGroup = self.view
  local function onRowRender( event )
   
      local row = event.row
      
      local rowTitle = display.newText( row, event.row.params.file, 0, 0, nil, 100 )
      rowTitle:setFillColor( 0 )
   
      rowTitle.anchorX = 0
      rowTitle.x = 0
      rowTitle.y = 56 -- half of 112 (current rowHeight)
  end
  
  tableView = widget.newTableView(
      {
        left = 0,
        top = 0,
        height = display.contentHeight-400,
        width = display.contentWidth,
        onRowRender = onRowRender,
        onRowTouch = onRowTouch,
        listener = scrollListener
      }
  )

  local lfs = require ( "lfs" )
  local path = system.pathForFile( "", system.DocumentsDirectory )

  local savedGames = {}

  for file in lfs.dir ( path ) do
      if string.find( file, ".db" ) then
        table.insert( savedGames, file )
        tableView:insertRow{
          rowHeight = 112,
          params = {file=file},  -- Include custom data in the row
          rowColor = { 
                  default = { 255, 255, 255},
                  over = { 255, 0, 0},
          },
        }
      end
  end
  
  deleteButton = widget.newButton(
    {
        width = 200,
        height = 100,
        defaultFile = "button.png",
        overFile = "button-over.png",
        fontSize= 60,
        labelColor = { default={255}, over={128} }
    }
  )
  
  deleteButton.x = display.actualContentWidth/1.5
  deleteButton.y = display.actualContentHeight*0.9
   
  deleteButton:setLabel( "Delete" )
  sceneGroup:insert( deleteButton )
  sceneGroup:insert( tableView )
end

function scene:destroy( event )
local sceneGroup = self.view
deleteButton:removeSelf() -- widgets must be manually removed
deleteButton = nil
    
  tableView:removeSelf()
  tableView = nil
end

scene:addEventListener( "create", scene )
scene:addEventListener( "destroy", scene )
return scene

 

Tapping on each row after a deletion will print:



onRowTouch (event.target.index): 1
onRowTouch (event.target.index): 2
onRowTouch (event.target.index): 4
onRowTouch (event.target.index): 5
onRowTouch (event.target.index): 6

 

 

If someone can confirm this is a bug I can file a bug report.



[TOPIC: post.html]
#2

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 768 posts
  • Corona SDK

I am wondering if it is a bug or design, as I can see cases where recalculating the index would cause some issues.

 

Let's say you populate a tableview and the index is used to refer to positions in an array (a common scenario).

When you then delete a row, you dont want the index to be recalculated, or else your array is gonna get mixed up the next time you access a row.

 

What you need to do in that case is to requery and rebuild the tableview, a kind of "refresh".

tableview:reloadData() will not work when items need to be added or removed.

 

Hope that makes sense somehow  :D



[TOPIC: post.html]
#3

J@V0

[GLOBAL: userInfoPane.html]
J@V0
  • Enthusiast

  • 43 posts
  • Corona SDK

But that would mean that you cannot delete multiple rows (one by one) on a given TableView without making such adjustments...

 

Which part would the "requery and rebuild the tableview" be? tableView:insertRow only? I've tried a couple of things but same result.



[TOPIC: post.html]
#4

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 768 posts
  • Corona SDK

  Best Answer

oh yes you can.

 

in the OnRowTouch function you use event.target, which points to the row itself, instead of event.target.index which is just the stored index from when the tableview was created.

 

i think my requery and rebuild statement is colored by how my app handle it.

 

i have a query function that pulls data from a sql server and stores it in an array.

after each query, i delete all rows and run a tableView:insertRow loop to repopulate the tableView.

 

how you get the source data used to populate the tableView may differ but the process should be close to identical.



[TOPIC: post.html]
#5

J@V0

[GLOBAL: userInfoPane.html]
J@V0
  • Enthusiast

  • 43 posts
  • Corona SDK

in the OnRowTouch function you use event.target, which points to the row itself, instead of event.target.index which is just the stored index from when the tableview was created.

 

I actually event.target.index in the loop when I do if i == row.index then with row being event.target

I then store that in globalData.rowIndexTapped

 

So I've changed my code to the following but the behavior hasn't changed. Can you see anything wrong?

 

local confirmDeleteFile
local onDeleteButtonRelease

local function RefreshTable ()
 print("refreshing table")
  local lfs = require ( "lfs" )
  local path = system.pathForFile( "", system.DocumentsDirectory )

  local savedGames = {}

  for file in lfs.dir ( path ) do
      if string.find( file, ".db" ) then
        table.insert( savedGames, file )
        tableView:insertRow{
          rowHeight = 112,
          params = {file=file},  -- Include custom data in the row
          rowColor = { 
                  default = { 255, 255, 255},
                  over = { 255, 0, 0},
          },
        }
      end
  end
  tableView:reloadData()
end


confirmDeleteFile = function ( event )
    if ( event.action == "clicked" ) then
      print("cliked confirmDeleteFile")
      local i = event.index
      if ( i == 1 ) then
        local result, reason = os.remove( system.pathForFile( globalData.fileTapped, system.DocumentsDirectory ) )
         tableView:deleteRows( { globalData.rowIndexTapped } )
         tableView:deleteAllRows()
         deleteButton:removeEventListener("tap", onDeleteButtonRelease)
         RefreshTable ()
      end
      print("done")
      return true -- indicates successful touch
    end
end


onDeleteButtonRelease = function (event)
  local alert = native.showAlert( "Delete saved game", "Are you sure you want to delete this game?", { "Yes", "No, cancel" }, confirmDeleteFile )
  return true -- indicates successful touch
end

The console prints:

refreshing table
onRowTouch (event.target.index): 5  -- tap on row 5
cliked confirmDeleteFile
refreshing table
done
onRowTouch (event.target.index): 4  -- tap on row 4
onRowTouch (event.target.index): 6  -- tap on row 5

 

 



[TOPIC: post.html]
#6

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 768 posts
  • Corona SDK

we code very different and it seems to be but a snippet, but I just did a test in my app where i printed event.target.index on clicking row 3, giving index = 3.

 

then i deleted row 3, did a sql requery and repopulated the tableview.

 

the new row 3 (previously row 4) also shows index 3 on print, so you must be doing something strange. I dont get that index behaviour.

 

i strongly recommend checking with the online corona documentation if you havent already, which is well made and up to date.



[TOPIC: post.html]
#7

J@V0

[GLOBAL: userInfoPane.html]
J@V0
  • Enthusiast

  • 43 posts
  • Corona SDK

oh that works now, not sure what I actually changed. Thanks!



[TOPIC: post.html]
#8

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 768 posts
  • Corona SDK

glad you figurered it out  :D




[topic_controls]
[/topic_controls]

Also tagged with one or more of these keywords: tableview