TableView and Changing Properties of Row Objects / Swipe to Delete Question

Kind Corona experts,

I am looking for help and suggestions on how to manipulate the objects that get put into table rows.  I’d like to have a delete button appear /disappear based on the swipeLeft gesture.  It would also be great to be able to move a text object left or right on the fly.

I’ve spent considerable time browsing the forums, where I’ve seen some older solutions, learned that rerendering a table currently requires deleting rows and recreating it, that old discussions that look promising use undocumented variables _view etc., and a mixture of daily builds, and of course I see some frustration among professional devs about the timing of “fixing” such things.  That’s not why I’m posting, but what an amazing and sharing community!

Instead, I’d like to know if what I propose in the code below is possible.  In particular see the comments I’ve put in the onRowTouch function.  I’d also welcome any suggestions on how to organize this basic table example better.

I will admit right up front that I’m only an occasional user and in this area don’t know enough to know if there’s an obvious bit of syntax that would work or if it simply can’t be done right now.  I’m using starter/public build Version 2013.2100

This seems like one of those “last mile” problems that somehow should have an obvious solution…  Thanks in advance for any ideas.

Dan

[lua]

– test of table with row delete code

    local widget = require( “widget” )

    – set up the data

    local datatable = {}  – holds records from which to build table

    local tbView – this is the tableView widget, forward declaration

    

    datatable = 

    {

        {

        id = 1,

        str = ‘Item One’

        },

        {

        id = 2,

        str = ‘Item Two’

        }

    }

    function populatetable()    

        if #datatable == 0 then

        else

            if tbView then

                tbView:deleteAllRows()

            end

            for i = 1, #datatable do

                local rowHeight = 50

                local rowColor = { default={ 1, 1, 1 }, over={ 1, 1, 1 } }

                local lineColor = {0.25, 0.25, 0.25, 0.5 }

                – Insert a row into the tableView    

                tbView:insertRow(

                    {

                        rowHeight = rowHeight,

                        rowColor = rowColor,

                        lineColor = lineColor

                    }

                    )

            end

        end

    end – populatetable

        

    – delete function

    local function onDelete ( event )

        local rowIndex = event.target.index

        local rowGroup = event.row        

        print (‘Delete tapped’)

        – delete the record code goes here

        return true

    end

    

    – render rows

    – for now a simple text line plus the delete button (starts invisible alpha = 0)

    – swipe left should make it visible (alpha = 1)

    

    local function onRowRender( event )

        local rowGroup = event.row      – Get reference to the row group

        local rowIndex = event.row.index

        local rowHeight = rowGroup.contentHeight

        local rowWidth = rowGroup.contentWidth

        

        local rowTitle = display.newText( rowGroup, datatable[rowIndex].str, 0, 0, “HelveticaNeue-Light”, 16 )

        rowTitle:setFillColor( 0, 0, 0, 1 )

        rowTitle.anchorX = 0

        rowTitle.x = 20

        rowTitle.y = rowHeight * 0.5

    

        local deleteButton = display.newText(“Delete”, 0, 0, “HelveticaNeue-Light”, 16)

        deleteButton:setFillColor(1,0,0,0)    –  ( change to 1,0,0,1 to start w/ delete showing)

        deleteButton.x = rowWidth - 100        

        deleteButton.y = rowHeight * 0.5

        deleteButton:addEventListener( “tap”, onDelete )

        rowGroup:insert(deleteButton)            

    end – onrowrender

    – process touches or swipe left to delete

    local function onRowTouch ( event )

        local phase = event.phase

        local rowIndex = event.target.index

        local rowGroup = event.row

        

        if (( phase == “swipeLeft” )) then

            print(‘swiped left’)

            – what I want to do is reveal the delete button by setting alpha to 1

            – deleteButton:setFillColor(1,0,0,1)

            – this would also be the place to do a little transition.to magic to

            – slide the text to the left…            

            – so, the 64k question is:  how to access objects in the row to change

            – their properties or move them around…

        end

        if ((phase == “release”) or (phase==“tap”)) then

            print(‘row tapped’)

            – row was touched or tapped so do other stuff…

        end

        return true            

    end    

    – create the table

        local listOptions =

        {

            left = 0,

            top = 100,

            height = 300,

            width = display.contentWidth,

            onRowRender = onRowRender,

            onRowTouch = onRowTouch,

            hideScrollBar = true,

            noLines = false,

            listener = scrollListener

        }

        tbView = widget.newTableView( listOptions )

    – populate the table

    populatetable()

[/lua]

In your rowRender function after you create the deleteButton set rowGroup.deleteButton = deleteButton. Then on tap you can call rowGroup.deleteButton.alpha = 1

Primoz - thanks so much for your explanation.  It pointed me in the right direction.  That and some advice you and others had on a similar post led me to experiment a bit on a real “slide to delete” option with the existing tableview. It seems it is possible, with a couple of hacks and some careful logic.

Here’s a version of my rough slide-to-delete table code.  It works in with version 2013.2100, and on device.  I welcome any suggestions, ideas, extensions or improvements.

[lua]

– test of table with row delete code

    local widget = require( “widget” )

    

    local delete =             --keeps track of whether a row has been swiped left (delete.active = true)

            {                --delete.row keeps track of what row in the tableview this is…

            active = false, --only one row in the tableview can be slid left for deletion at a time

            row = 0

            }

    – set up the data

    local datatable = {}  – holds records from which to build table

    local tbView – this is the tableView widget, forward declaration

    

    for i = 1, 50 do

        datatable[i] = 

        {

        id = i,

        str = "Item "…tostring(i),

        deleted = false

        }

    end

    function populatetable()    

        if #datatable == 0 then

        else

            if tbView then

                tbView:deleteAllRows()

            end

            for i = 1, #datatable do

                local rowHeight = 50

                local rowColor = { default={ 1, 1, 1 }, over={ 1, 1, 1 } }

                local lineColor = {0.25, 0.25, 0.25, 0.5 }

                – Insert a row into the tableView if it isn’t deleted

                if datatable[i].deleted then

                    print(‘skipping deleted row’)

                else

                    tbView:insertRow(

                        {

                            rowHeight = rowHeight,

                            rowColor = rowColor,

                            lineColor = lineColor

                        }

                        )

                end

            end

        end

    end – populatetable

    – process touches or swipe left to delete

    local function onRowTouch ( event )

        local phase = event.phase

        local id = event.target.id

        local name = event.target.name

        local rowIndex = event.target.index

        local rowGroup = event.row

        

        local function sliderow (therow, direction)

        

            if tbView._view._rows[therow]._view then

                if direction == “left” then

                        transition.moveBy( tbView._view._rows[therow]._view[4], { x=-50, time=250 } )

                        transition.moveBy( tbView._view._rows[therow]._view[3], { x=-50, time=250 } )

                        delete.active = true

                        delete.row = therow

                end

                

                if direction == “right” then

                        transition.moveBy( tbView._view._rows[therow]._view[4], { x=50, time=250 } )

                        transition.moveBy( tbView._view._rows[therow]._view[3], { x=50, time=250 } )

                        delete.active = false

                        delete.row = 0

                end

                

                if direction == “erase” then

                        transition.fadeOut( tbView._view._rows[therow]._view, {time=100 } )

                        print('About to delete row: ', therow, datatable[therow].str)

                        datatable[therow].deleted = true

                        delete.active = false

                        delete.row = 0

                        tbView:deleteRow(therow)

                end        

            end

        end – function sliderow 

        

        if ( phase == “swipeLeft”) then

            print(‘swiped left’)

            if delete.active == false then

                sliderow(rowIndex, “left”)

            else

                sliderow(delete.row, “right”)

            end

        else

            if (phase == “swipeRight”) then

                print(‘swiped right’)

                if delete.active then

                    sliderow(delete.row, “right”)

                else

                    --sliderow(rowIndex, “right”)                    

                end

            end

        end        

        if ((phase == “ended”) or (phase == “tap”)) then

            if (name == ‘del’) then

                  print(‘delete code  goes here’)

                  sliderow(delete.row, “erase”)

              else

                if delete.active then

                    sliderow(delete.row, “right”)

                    

                end

            end

        end

        return true

    end    

    

    local function onRowRender( event )

        local rowGroup = event.row      – Get reference to the row group

        local rowIndex = event.row.index

        local rowHeight = rowGroup.contentHeight

        local rowWidth = rowGroup.contentWidth

        

        local rowTitle = display.newText( rowGroup, datatable[rowIndex].str, 0, 0, “HelveticaNeue-Light”, 16 )

        rowTitle:setFillColor( 0, 0, 0, 1 )

        rowTitle.anchorX = 0

        rowTitle.x = 20

        rowTitle.y = rowHeight * 0.5

    

        local deleteButton = display.newText(“Delete”, 0, 0, “HelveticaNeue-Light”, 16)

         deleteButton:setFillColor(1,0,0,1)    –  ( change to 1,0,0,1 to start w/ delete showing)

        deleteButton.x = rowWidth + deleteButton.width*.5        

        deleteButton.y = rowHeight * 0.5

        rowGroup.deleteButton = deleteButton

        deleteButton.secretIndex = rowIndex

        deleteButton.name = ‘del’

        deleteButton:addEventListener( “touch”, onRowTouch )

        rowGroup:insert(deleteButton)

        

        – if the active delete row scrolled to far off the screen it will be recreated

        – as though not active.  IOTW, if you scroll away w/ delete active it deactivates

        – That’s the desired behavior, but if so, need to reset: delete.active flags

        if delete.active then

            delete.active = false

            delete.row = 0

        end                

    end – onrowrender

    – create the table

        local listOptions =

        {

            x = 0.5 * display.contentWidth,

            y = 0.5 * display.contentHeight,

            height = display.contentHeight,

            width = display.contentWidth,

            onRowRender = onRowRender,

            onRowTouch = onRowTouch,

            hideScrollBar = true,

            noLines = false,

            listener = scrollListener

        }

        tbView = widget.newTableView( listOptions )

    – populate the table

    populatetable()

[/lua]

Looks good but keep in mind that this might change in a future release:

tbView._view._rows[therow]._view[4]

I would suggest that you keep a reference to the rows view in delete table instead of the index.

instead of passing sliderow(rowIndex, “left”)

try sliderow( rowGroup , “left”)

then instead of the _rows access 

tbView._view._rows[therow]._view[4]

just use

therow[4]

I think the view also has an index property on it if you need it so therow.index will give you the index. If it doesn’t then just set it at the begining of your touch listener like rowGroup.index = event.target.index

You can access the line from the rowGroup also. It should be [2]. Note that things you add yourself you can reference with names so you don’t have to look for the number. And the numbers might change due to your settings. For example when you create myText = display.newText(…

and you add it to the row with rowGroup:insert(myText) you can also set a reference to it on the group like so: rowGroup.myText = myText

For locking the table view you can use this: tableView:setIsLocked( lockedState )

lockedState - true/false

This is a public method but someone forgot to add it to the docs.

Primoz -

Great tips!  Searching on the table locking (tableView:setIsLocked) reveals that this only works in 2109 and newer, but there is a less elegant way to lock the table for the starter version.  I put a note in the code.

So, I’m calling this good enough for now, and hope it helps someone else who’s starting out.

[lua]

– basic swipe to delete in a table code

– it locks screen scrolling once a delete item has been swiped

– (for this to work with the public release .2100 it uses an undocumented internal call - see comments)

– more elegant is the tableView:setIsLocked(t/f) option, available in .2109 and later…

    local widget = require( “widget” )

    

    local delete =             --keeps track of whether a row has been swiped left (delete.active = true)

            {                --delete.row keeps track of what row in the tableview this is…

            active = false, --only one row in the tableview can be slid left for deletion at a time

            rowgroup = nil

            }

    – set up the data

    local datatable = {}  – holds records from which to build table

    local tbView – this is the tableView widget, forward declaration

    

    for i = 1, 50 do

        datatable[i] = 

        {

        id = i,

        str = "Item "…tostring(i),

        deleted = false                    – deleting is really just setting a “deleted” flag

        }

    end

    function populatetable()    

        if #datatable == 0 then

        else

            if tbView then

                tbView:deleteAllRows()

            end

            for i = 1, #datatable do

                local rowHeight = 50

                local rowColor = { default={ 1, 1, 1 }, over={ 1, 1, 1 } }

                local lineColor = {0.25, 0.25, 0.25, 0.5 }

                – Insert a row into the tableView if it isn’t deleted

                if datatable[i].deleted then

                    print(‘skipping deleted row’)

                else

                    tbView:insertRow(

                        {

                            rowHeight = rowHeight,

                            rowColor = rowColor,

                            lineColor = lineColor

                        }

                        )

                end

            end

        end

    end – populatetable

    – process touches or swipe left to delete

    local function onRowTouch ( event )

        local phase = event.phase

        local id = event.target.id

        local name = event.target.name

        local rowIndex = event.target.index

        local rowGroup = event.row

        

        – this version passes a rowgroup to sliderow, instead of an index “therow”

        local function sliderow (therowgroup, direction)

            

            – If not using scroll lock when delete is active check if row is on screen:

            – is there a better way to see if a table row is on screen?

            – need to be sure that  sliderow doesn’t called on an off-screen row        

            – if tbView._view._rows[therowgroup.index]._view then

                if direction == “left” then

                        transition.moveBy( therowgroup[4], { x=-50, time=250 } )

                        transition.moveBy( therowgroup[3], { x=-50, time=250 } )

                        delete.active = true

                        delete.rowgroup = therowgroup

                end

                

                if direction == “right” then

                        transition.moveBy( therowgroup[4], { x=50, time=250 } )

                        transition.moveBy( therowgroup[3], { x=50, time=250 } )

                        delete.active = false

                        delete.rowgroup = nil

                end

                

                if direction == “erase” then

                        transition.fadeOut( therowgroup, {time=100 } )

                        print('About to delete row: ', therowgroup.index, datatable[therowgroup.index].str)

                        datatable[therowgroup.index].deleted = true

                        delete.active = false

                        delete.rowgroup = nil

                        tbView:deleteRow(therowgroup.index)

                end        

            --end

        end – function sliderow 

        

        if ( phase == “swipeLeft”) then

            print(‘swiped left’)

            if delete.active == false then

                tbView._view._isVerticalScrollingDisabled = true  – bad form but works w/ public release .2100.  see next line

                –    tbView:setIsLocked(true)    

                sliderow(rowGroup, “left”)

            else

                sliderow(delete.rowgroup, “right”)

                tbView._view._isVerticalScrollingDisabled = false

            end

        else

            if (phase == “swipeRight”) then

                print(‘swiped right’)

                if delete.active then

                    sliderow(delete.rowgroup, “right”)

                    tbView._view._isVerticalScrollingDisabled = false  – bad form but works w/ public release .2100.  see next line

                    –    tbView:setIsLocked(false)  – use this with versions .2109 and later

                else

                    – swipe right not related to deleting - ignore

                end

            end

        end        

        if ((phase == “ended”) or (phase == “tap”)) then

            if (name == ‘del’) then

                  print(‘delete code  goes here’)

                  sliderow(delete.rowgroup, “erase”)

                 tbView._view._isVerticalScrollingDisabled = false  – bad form but works w/ public release .2100.  see next line

                 – tbView:setIsLocked(false)

              else

                if delete.active then

                    sliderow(delete.rowgroup, “right”)

                 tbView._view._isVerticalScrollingDisabled = false  – bad form but works w/ public release .2100.  see next line

                –    tbView:setIsLocked(false)

                end

            end

        end

        return true

    end    

    

    local function onRowRender( event )

        local rowGroup = event.row      – Get reference to the row group

        local rowIndex = event.row.index

        local rowHeight = rowGroup.contentHeight

        local rowWidth = rowGroup.contentWidth

        

        local rowTitle = display.newText( rowGroup, datatable[rowIndex].str, 0, 0, “HelveticaNeue-Light”, 16 )

        rowTitle:setFillColor( 0, 0, 0, 1 )

        rowTitle.anchorX = 0

        rowTitle.x = 20

        rowTitle.y = rowHeight * 0.5

    

        local deleteButton = display.newText(“Delete”, 0, 0, “HelveticaNeue-Light”, 16)

         deleteButton:setFillColor(1,0,0,1)    –  ( change to 1,0,0,1 to start w/ delete showing)

        deleteButton.x = rowWidth + deleteButton.width*.5        

        deleteButton.y = rowHeight * 0.5

        rowGroup.deleteButton = deleteButton

        deleteButton.secretIndex = rowIndex

        deleteButton.name = ‘del’

        deleteButton:addEventListener( “touch”, onRowTouch )

        rowGroup:insert(deleteButton)

        

        – Now probably not needed if the scroll locking works correctly…

        – if the active delete row scrolled too far off the screen it will be recreated

        – as though not active.  IOTW, if you scroll away w/ delete active it deactivates

        – That’s the desired behavior, but if so, need to reset: delete.active flags

        if delete.active then

            delete.active = false

            delete.rowgroup = nil

        end                

    end – onrowrender

    – create the table

        local listOptions =

        {

            x = 0.5 * display.contentWidth,

            y = 0.5 * display.contentHeight,

            height = display.contentHeight,

            width = display.contentWidth,

            onRowRender = onRowRender,

            onRowTouch = onRowTouch,

            hideScrollBar = true,

            noLines = false,

            listener = scrollListener

        }

        tbView = widget.newTableView( listOptions )

    – populate the table

    populatetable()

[/lua]

Ah right I’m using the code from github which is from 2114 so it’s there. I suggest you do the same so you don’t get any surprises on the next build.

https://github.com/coronalabs/framework-widget

In your rowRender function after you create the deleteButton set rowGroup.deleteButton = deleteButton. Then on tap you can call rowGroup.deleteButton.alpha = 1

Primoz - thanks so much for your explanation.  It pointed me in the right direction.  That and some advice you and others had on a similar post led me to experiment a bit on a real “slide to delete” option with the existing tableview. It seems it is possible, with a couple of hacks and some careful logic.

Here’s a version of my rough slide-to-delete table code.  It works in with version 2013.2100, and on device.  I welcome any suggestions, ideas, extensions or improvements.

[lua]

– test of table with row delete code

    local widget = require( “widget” )

    

    local delete =             --keeps track of whether a row has been swiped left (delete.active = true)

            {                --delete.row keeps track of what row in the tableview this is…

            active = false, --only one row in the tableview can be slid left for deletion at a time

            row = 0

            }

    – set up the data

    local datatable = {}  – holds records from which to build table

    local tbView – this is the tableView widget, forward declaration

    

    for i = 1, 50 do

        datatable[i] = 

        {

        id = i,

        str = "Item "…tostring(i),

        deleted = false

        }

    end

    function populatetable()    

        if #datatable == 0 then

        else

            if tbView then

                tbView:deleteAllRows()

            end

            for i = 1, #datatable do

                local rowHeight = 50

                local rowColor = { default={ 1, 1, 1 }, over={ 1, 1, 1 } }

                local lineColor = {0.25, 0.25, 0.25, 0.5 }

                – Insert a row into the tableView if it isn’t deleted

                if datatable[i].deleted then

                    print(‘skipping deleted row’)

                else

                    tbView:insertRow(

                        {

                            rowHeight = rowHeight,

                            rowColor = rowColor,

                            lineColor = lineColor

                        }

                        )

                end

            end

        end

    end – populatetable

    – process touches or swipe left to delete

    local function onRowTouch ( event )

        local phase = event.phase

        local id = event.target.id

        local name = event.target.name

        local rowIndex = event.target.index

        local rowGroup = event.row

        

        local function sliderow (therow, direction)

        

            if tbView._view._rows[therow]._view then

                if direction == “left” then

                        transition.moveBy( tbView._view._rows[therow]._view[4], { x=-50, time=250 } )

                        transition.moveBy( tbView._view._rows[therow]._view[3], { x=-50, time=250 } )

                        delete.active = true

                        delete.row = therow

                end

                

                if direction == “right” then

                        transition.moveBy( tbView._view._rows[therow]._view[4], { x=50, time=250 } )

                        transition.moveBy( tbView._view._rows[therow]._view[3], { x=50, time=250 } )

                        delete.active = false

                        delete.row = 0

                end

                

                if direction == “erase” then

                        transition.fadeOut( tbView._view._rows[therow]._view, {time=100 } )

                        print('About to delete row: ', therow, datatable[therow].str)

                        datatable[therow].deleted = true

                        delete.active = false

                        delete.row = 0

                        tbView:deleteRow(therow)

                end        

            end

        end – function sliderow 

        

        if ( phase == “swipeLeft”) then

            print(‘swiped left’)

            if delete.active == false then

                sliderow(rowIndex, “left”)

            else

                sliderow(delete.row, “right”)

            end

        else

            if (phase == “swipeRight”) then

                print(‘swiped right’)

                if delete.active then

                    sliderow(delete.row, “right”)

                else

                    --sliderow(rowIndex, “right”)                    

                end

            end

        end        

        if ((phase == “ended”) or (phase == “tap”)) then

            if (name == ‘del’) then

                  print(‘delete code  goes here’)

                  sliderow(delete.row, “erase”)

              else

                if delete.active then

                    sliderow(delete.row, “right”)

                    

                end

            end

        end

        return true

    end    

    

    local function onRowRender( event )

        local rowGroup = event.row      – Get reference to the row group

        local rowIndex = event.row.index

        local rowHeight = rowGroup.contentHeight

        local rowWidth = rowGroup.contentWidth

        

        local rowTitle = display.newText( rowGroup, datatable[rowIndex].str, 0, 0, “HelveticaNeue-Light”, 16 )

        rowTitle:setFillColor( 0, 0, 0, 1 )

        rowTitle.anchorX = 0

        rowTitle.x = 20

        rowTitle.y = rowHeight * 0.5

    

        local deleteButton = display.newText(“Delete”, 0, 0, “HelveticaNeue-Light”, 16)

         deleteButton:setFillColor(1,0,0,1)    –  ( change to 1,0,0,1 to start w/ delete showing)

        deleteButton.x = rowWidth + deleteButton.width*.5        

        deleteButton.y = rowHeight * 0.5

        rowGroup.deleteButton = deleteButton

        deleteButton.secretIndex = rowIndex

        deleteButton.name = ‘del’

        deleteButton:addEventListener( “touch”, onRowTouch )

        rowGroup:insert(deleteButton)

        

        – if the active delete row scrolled to far off the screen it will be recreated

        – as though not active.  IOTW, if you scroll away w/ delete active it deactivates

        – That’s the desired behavior, but if so, need to reset: delete.active flags

        if delete.active then

            delete.active = false

            delete.row = 0

        end                

    end – onrowrender

    – create the table

        local listOptions =

        {

            x = 0.5 * display.contentWidth,

            y = 0.5 * display.contentHeight,

            height = display.contentHeight,

            width = display.contentWidth,

            onRowRender = onRowRender,

            onRowTouch = onRowTouch,

            hideScrollBar = true,

            noLines = false,

            listener = scrollListener

        }

        tbView = widget.newTableView( listOptions )

    – populate the table

    populatetable()

[/lua]

Looks good but keep in mind that this might change in a future release:

tbView._view._rows[therow]._view[4]

I would suggest that you keep a reference to the rows view in delete table instead of the index.

instead of passing sliderow(rowIndex, “left”)

try sliderow( rowGroup , “left”)

then instead of the _rows access 

tbView._view._rows[therow]._view[4]

just use

therow[4]

I think the view also has an index property on it if you need it so therow.index will give you the index. If it doesn’t then just set it at the begining of your touch listener like rowGroup.index = event.target.index

You can access the line from the rowGroup also. It should be [2]. Note that things you add yourself you can reference with names so you don’t have to look for the number. And the numbers might change due to your settings. For example when you create myText = display.newText(…

and you add it to the row with rowGroup:insert(myText) you can also set a reference to it on the group like so: rowGroup.myText = myText

For locking the table view you can use this: tableView:setIsLocked( lockedState )

lockedState - true/false

This is a public method but someone forgot to add it to the docs.

Primoz -

Great tips!  Searching on the table locking (tableView:setIsLocked) reveals that this only works in 2109 and newer, but there is a less elegant way to lock the table for the starter version.  I put a note in the code.

So, I’m calling this good enough for now, and hope it helps someone else who’s starting out.

[lua]

– basic swipe to delete in a table code

– it locks screen scrolling once a delete item has been swiped

– (for this to work with the public release .2100 it uses an undocumented internal call - see comments)

– more elegant is the tableView:setIsLocked(t/f) option, available in .2109 and later…

    local widget = require( “widget” )

    

    local delete =             --keeps track of whether a row has been swiped left (delete.active = true)

            {                --delete.row keeps track of what row in the tableview this is…

            active = false, --only one row in the tableview can be slid left for deletion at a time

            rowgroup = nil

            }

    – set up the data

    local datatable = {}  – holds records from which to build table

    local tbView – this is the tableView widget, forward declaration

    

    for i = 1, 50 do

        datatable[i] = 

        {

        id = i,

        str = "Item "…tostring(i),

        deleted = false                    – deleting is really just setting a “deleted” flag

        }

    end

    function populatetable()    

        if #datatable == 0 then

        else

            if tbView then

                tbView:deleteAllRows()

            end

            for i = 1, #datatable do

                local rowHeight = 50

                local rowColor = { default={ 1, 1, 1 }, over={ 1, 1, 1 } }

                local lineColor = {0.25, 0.25, 0.25, 0.5 }

                – Insert a row into the tableView if it isn’t deleted

                if datatable[i].deleted then

                    print(‘skipping deleted row’)

                else

                    tbView:insertRow(

                        {

                            rowHeight = rowHeight,

                            rowColor = rowColor,

                            lineColor = lineColor

                        }

                        )

                end

            end

        end

    end – populatetable

    – process touches or swipe left to delete

    local function onRowTouch ( event )

        local phase = event.phase

        local id = event.target.id

        local name = event.target.name

        local rowIndex = event.target.index

        local rowGroup = event.row

        

        – this version passes a rowgroup to sliderow, instead of an index “therow”

        local function sliderow (therowgroup, direction)

            

            – If not using scroll lock when delete is active check if row is on screen:

            – is there a better way to see if a table row is on screen?

            – need to be sure that  sliderow doesn’t called on an off-screen row        

            – if tbView._view._rows[therowgroup.index]._view then

                if direction == “left” then

                        transition.moveBy( therowgroup[4], { x=-50, time=250 } )

                        transition.moveBy( therowgroup[3], { x=-50, time=250 } )

                        delete.active = true

                        delete.rowgroup = therowgroup

                end

                

                if direction == “right” then

                        transition.moveBy( therowgroup[4], { x=50, time=250 } )

                        transition.moveBy( therowgroup[3], { x=50, time=250 } )

                        delete.active = false

                        delete.rowgroup = nil

                end

                

                if direction == “erase” then

                        transition.fadeOut( therowgroup, {time=100 } )

                        print('About to delete row: ', therowgroup.index, datatable[therowgroup.index].str)

                        datatable[therowgroup.index].deleted = true

                        delete.active = false

                        delete.rowgroup = nil

                        tbView:deleteRow(therowgroup.index)

                end        

            --end

        end – function sliderow 

        

        if ( phase == “swipeLeft”) then

            print(‘swiped left’)

            if delete.active == false then

                tbView._view._isVerticalScrollingDisabled = true  – bad form but works w/ public release .2100.  see next line

                –    tbView:setIsLocked(true)    

                sliderow(rowGroup, “left”)

            else

                sliderow(delete.rowgroup, “right”)

                tbView._view._isVerticalScrollingDisabled = false

            end

        else

            if (phase == “swipeRight”) then

                print(‘swiped right’)

                if delete.active then

                    sliderow(delete.rowgroup, “right”)

                    tbView._view._isVerticalScrollingDisabled = false  – bad form but works w/ public release .2100.  see next line

                    –    tbView:setIsLocked(false)  – use this with versions .2109 and later

                else

                    – swipe right not related to deleting - ignore

                end

            end

        end        

        if ((phase == “ended”) or (phase == “tap”)) then

            if (name == ‘del’) then

                  print(‘delete code  goes here’)

                  sliderow(delete.rowgroup, “erase”)

                 tbView._view._isVerticalScrollingDisabled = false  – bad form but works w/ public release .2100.  see next line

                 – tbView:setIsLocked(false)

              else

                if delete.active then

                    sliderow(delete.rowgroup, “right”)

                 tbView._view._isVerticalScrollingDisabled = false  – bad form but works w/ public release .2100.  see next line

                –    tbView:setIsLocked(false)

                end

            end

        end

        return true

    end    

    

    local function onRowRender( event )

        local rowGroup = event.row      – Get reference to the row group

        local rowIndex = event.row.index

        local rowHeight = rowGroup.contentHeight

        local rowWidth = rowGroup.contentWidth

        

        local rowTitle = display.newText( rowGroup, datatable[rowIndex].str, 0, 0, “HelveticaNeue-Light”, 16 )

        rowTitle:setFillColor( 0, 0, 0, 1 )

        rowTitle.anchorX = 0

        rowTitle.x = 20

        rowTitle.y = rowHeight * 0.5

    

        local deleteButton = display.newText(“Delete”, 0, 0, “HelveticaNeue-Light”, 16)

         deleteButton:setFillColor(1,0,0,1)    –  ( change to 1,0,0,1 to start w/ delete showing)

        deleteButton.x = rowWidth + deleteButton.width*.5        

        deleteButton.y = rowHeight * 0.5

        rowGroup.deleteButton = deleteButton

        deleteButton.secretIndex = rowIndex

        deleteButton.name = ‘del’

        deleteButton:addEventListener( “touch”, onRowTouch )

        rowGroup:insert(deleteButton)

        

        – Now probably not needed if the scroll locking works correctly…

        – if the active delete row scrolled too far off the screen it will be recreated

        – as though not active.  IOTW, if you scroll away w/ delete active it deactivates

        – That’s the desired behavior, but if so, need to reset: delete.active flags

        if delete.active then

            delete.active = false

            delete.rowgroup = nil

        end                

    end – onrowrender

    – create the table

        local listOptions =

        {

            x = 0.5 * display.contentWidth,

            y = 0.5 * display.contentHeight,

            height = display.contentHeight,

            width = display.contentWidth,

            onRowRender = onRowRender,

            onRowTouch = onRowTouch,

            hideScrollBar = true,

            noLines = false,

            listener = scrollListener

        }

        tbView = widget.newTableView( listOptions )

    – populate the table

    populatetable()

[/lua]

Ah right I’m using the code from github which is from 2114 so it’s there. I suggest you do the same so you don’t get any surprises on the next build.

https://github.com/coronalabs/framework-widget