Tutorial code on advanced table view is not working

I copy pasted the tutorial code given at the link https://coronalabs.com/blog/2014/03/04/tutorial-advanced-tableview-tactics/

local navBarHeight = 60 local tabBarHeight = 50 local myList = widget.newTableView { top = navBarHeight, width = display.contentWidth, height = display.contentHeight - navBarHeight - tabBarHeight, onRowRender = onRowRender, onRowTouch = onRowTouch, listener = scrollListener } local myData = {} myData[1] = { name="Fred", phone="555-555-1234" } myData[2] = { name="Barney", phone="555-555-1235" } myData[3] = { name="Wilma", phone="555-555-1236" } myData[4] = { name="Betty", phone="555-555-1237" } myData[5] = { name="Pebbles", phone="555-555-1238" } myData[6] = { name="BamBam", phone="555-555-1239" } myData[7] = { name="Dino", phone="555-555-1240" } for i = 1, #myData do myList:insertRow{ rowHeight = 60, isCategory = false, rowColor = { 1, 1, 1 }, lineColor = { 0.90, 0.90, 0.90 } } end

It gives the following error:

22:21:54.105  ERROR: Runtime error

22:21:54.105  H:\AppDev\Corona\WidgetDemo\main.lua:3: attempt to index global ‘widget’ (a nil value)

22:21:54.105  stack traceback:

22:21:54.105  H:\AppDev\Corona\WidgetDemo\main.lua:3: in main chunk

I could not figure out what is wrong in line 3.

Hi and welcome to the forums. You need to include the widget library before you can use it. At line 1 add:

local widget = require("widget")

Rob

Thanks Rob.

Don’t you think you should add that code in your tutorial so that others don’t face the same issue.

I combined the code that you had shown in four sections. After executing, the data is not shown. Only the table view with the divider lines that scrolls.

Can you have a look why it’s not working?

local widget = require "widget" local navBarHeight = 60 local tabBarHeight = 50 local myList = widget.newTableView { top = navBarHeight, width = display.contentWidth, height = display.contentHeight - navBarHeight - tabBarHeight, onRowRender = onRowRender, onRowTouch = onRowTouch, listener = scrollListener } local myData = {} myData[1] = { name="Fred", phone="555-555-1234" } myData[2] = { name="Barney", phone="555-555-1235" } myData[3] = { name="Wilma", phone="555-555-1236" } myData[4] = { name="Betty", phone="555-555-1237" } myData[5] = { name="Pebbles", phone="555-555-1238" } myData[6] = { name="BamBam", phone="555-555-1239" } myData[7] = { name="Dino", phone="555-555-1240" } for i = 1, #myData do myList:insertRow{ rowHeight = 60, isCategory = false, rowColor = { 1, 1, 1 }, lineColor = { 0.90, 0.90, 0.90 } } end local function onRowRender( event ) --Set up the localized variables to be passed via the event table local row = event.row local id = row.index row.bg = display.newRect( 0, 0, display.contentWidth, 60 ) row.bg.anchorX = 0 row.bg.anchorY = 0 row.bg:setFillColor( 1, 1, 1 ) row:insert( row.bg ) row.nameText = display.newText( myData[id].name, 12, 0, native.systemFontBold, 18 ) row.nameText.anchorX = 0 row.nameText.anchorY = 0.5 row.nameText:setFillColor( 0 ) row.nameText.y = 20 row.nameText.x = 42 row.phoneText = display.newText( myData[id].phone, 12, 0, native.systemFont, 18 ) row.phoneText.anchorX = 0 row.phoneText.anchorY = 0.5 row.phoneText:setFillColor( 0.5 ) row.phoneText.y = 40 row.phoneText.x = 42 row.rightArrow = display.newImageRect( "rightarrow.png", 15 , 40, 40 ) row.rightArrow.x = display.contentWidth - 20 row.rightArrow.y = row.height / 2 row:insert( row.nameText ) row:insert( row.phoneText ) row:insert( row.rightArrow ) return true end local function onRowRender( event ) --Set up the localized variables to be passed via the event table local row = event.row local id = row.index local params = event.row.params row.bg = display.newRect( 0, 0, display.contentWidth, 60 ) row.bg.anchorX = 0 row.bg.anchorY = 0 row.bg:setFillColor( 1, 1, 1 ) row:insert( row.bg ) if ( event.row.params ) then row.nameText = display.newText( params.name, 12, 0, native.systemFontBold, 18 ) row.nameText.anchorX = 0 row.nameText.anchorY = 0.5 row.nameText:setFillColor( 0 ) row.nameText.y = 20 row.nameText.x = 42 row.phoneText = display.newText( params.phone, 12, 0, native.systemFont, 18 ) row.phoneText.anchorX = 0 row.phoneText.anchorY = 0.5 row.phoneText:setFillColor( 0.5 ) row.phoneText.y = 40 row.phoneText.x = 42 row.rightArrow = display.newImageRect( "rightarrow.png", 15 , 40, 40 ) row.rightArrow.x = display.contentWidth - 20 row.rightArrow.y = row.height / 2 row:insert( row.nameText ) row:insert( row.phoneText ) row:insert( row.rightArrow ) end return true end for i = 1, #myData do myList:insertRow{ rowHeight = 60, isCategory = false, rowColor = { 1, 1, 1 }, lineColor = { 0.90, 0.90, 0.90 }, params = { name = myData[i].name, phone = myData[i].phone } } end

I think the important thing is in the title:  “Advanced” which means there is an expectation before you use this tutorial, you already know how to use tableViews. Secondly, this is a tutorial about different tactics that can be applied to tableViews. It’s not a tableView tutorial. Again, with an assumption that you understand tableViews before you apply these advanced concepts. 

I don’t know that you can take the separate parts of that tutorial and assemble a working tableView example.

Now as to why your code doesn’t work. It’s important to understand the concept of scope. Lua is a single pass compiler. That is variables, objects and functions have to be defined before you can use them, unlike a language like C that is two-pass and gathers symbols and assigns addresses then goes back on the 2nd pass and plugs the values in.  With a one-pass system, when Lua sees your tableView constructor, the value of onRowRender, onRowTouch and listener are nil.  Therefore the tableView has no functions to call. You don’t define those functions until later. 

With Lua you define the functions first, then call the constructor afterwards and then you can insert the rows.  So put the:

local myList = widget.newTableView { top = navBarHeight, width = display.contentWidth, height = display.contentHeight - navBarHeight - tabBarHeight, onRowRender = onRowRender, onRowTouch = onRowTouch, listener = scrollListener }

after your onRowRendere function and before the insert loop. You also have two insert loops where you likely only want one.

Rob

Hi and welcome to the forums. You need to include the widget library before you can use it. At line 1 add:

local widget = require("widget")

Rob

Thanks Rob.

Don’t you think you should add that code in your tutorial so that others don’t face the same issue.

I combined the code that you had shown in four sections. After executing, the data is not shown. Only the table view with the divider lines that scrolls.

Can you have a look why it’s not working?

local widget = require "widget" local navBarHeight = 60 local tabBarHeight = 50 local myList = widget.newTableView { top = navBarHeight, width = display.contentWidth, height = display.contentHeight - navBarHeight - tabBarHeight, onRowRender = onRowRender, onRowTouch = onRowTouch, listener = scrollListener } local myData = {} myData[1] = { name="Fred", phone="555-555-1234" } myData[2] = { name="Barney", phone="555-555-1235" } myData[3] = { name="Wilma", phone="555-555-1236" } myData[4] = { name="Betty", phone="555-555-1237" } myData[5] = { name="Pebbles", phone="555-555-1238" } myData[6] = { name="BamBam", phone="555-555-1239" } myData[7] = { name="Dino", phone="555-555-1240" } for i = 1, #myData do myList:insertRow{ rowHeight = 60, isCategory = false, rowColor = { 1, 1, 1 }, lineColor = { 0.90, 0.90, 0.90 } } end local function onRowRender( event ) --Set up the localized variables to be passed via the event table local row = event.row local id = row.index row.bg = display.newRect( 0, 0, display.contentWidth, 60 ) row.bg.anchorX = 0 row.bg.anchorY = 0 row.bg:setFillColor( 1, 1, 1 ) row:insert( row.bg ) row.nameText = display.newText( myData[id].name, 12, 0, native.systemFontBold, 18 ) row.nameText.anchorX = 0 row.nameText.anchorY = 0.5 row.nameText:setFillColor( 0 ) row.nameText.y = 20 row.nameText.x = 42 row.phoneText = display.newText( myData[id].phone, 12, 0, native.systemFont, 18 ) row.phoneText.anchorX = 0 row.phoneText.anchorY = 0.5 row.phoneText:setFillColor( 0.5 ) row.phoneText.y = 40 row.phoneText.x = 42 row.rightArrow = display.newImageRect( "rightarrow.png", 15 , 40, 40 ) row.rightArrow.x = display.contentWidth - 20 row.rightArrow.y = row.height / 2 row:insert( row.nameText ) row:insert( row.phoneText ) row:insert( row.rightArrow ) return true end local function onRowRender( event ) --Set up the localized variables to be passed via the event table local row = event.row local id = row.index local params = event.row.params row.bg = display.newRect( 0, 0, display.contentWidth, 60 ) row.bg.anchorX = 0 row.bg.anchorY = 0 row.bg:setFillColor( 1, 1, 1 ) row:insert( row.bg ) if ( event.row.params ) then row.nameText = display.newText( params.name, 12, 0, native.systemFontBold, 18 ) row.nameText.anchorX = 0 row.nameText.anchorY = 0.5 row.nameText:setFillColor( 0 ) row.nameText.y = 20 row.nameText.x = 42 row.phoneText = display.newText( params.phone, 12, 0, native.systemFont, 18 ) row.phoneText.anchorX = 0 row.phoneText.anchorY = 0.5 row.phoneText:setFillColor( 0.5 ) row.phoneText.y = 40 row.phoneText.x = 42 row.rightArrow = display.newImageRect( "rightarrow.png", 15 , 40, 40 ) row.rightArrow.x = display.contentWidth - 20 row.rightArrow.y = row.height / 2 row:insert( row.nameText ) row:insert( row.phoneText ) row:insert( row.rightArrow ) end return true end for i = 1, #myData do myList:insertRow{ rowHeight = 60, isCategory = false, rowColor = { 1, 1, 1 }, lineColor = { 0.90, 0.90, 0.90 }, params = { name = myData[i].name, phone = myData[i].phone } } end

I think the important thing is in the title:  “Advanced” which means there is an expectation before you use this tutorial, you already know how to use tableViews. Secondly, this is a tutorial about different tactics that can be applied to tableViews. It’s not a tableView tutorial. Again, with an assumption that you understand tableViews before you apply these advanced concepts. 

I don’t know that you can take the separate parts of that tutorial and assemble a working tableView example.

Now as to why your code doesn’t work. It’s important to understand the concept of scope. Lua is a single pass compiler. That is variables, objects and functions have to be defined before you can use them, unlike a language like C that is two-pass and gathers symbols and assigns addresses then goes back on the 2nd pass and plugs the values in.  With a one-pass system, when Lua sees your tableView constructor, the value of onRowRender, onRowTouch and listener are nil.  Therefore the tableView has no functions to call. You don’t define those functions until later. 

With Lua you define the functions first, then call the constructor afterwards and then you can insert the rows.  So put the:

local myList = widget.newTableView { top = navBarHeight, width = display.contentWidth, height = display.contentHeight - navBarHeight - tabBarHeight, onRowRender = onRowRender, onRowTouch = onRowTouch, listener = scrollListener }

after your onRowRendere function and before the insert loop. You also have two insert loops where you likely only want one.

Rob