Network.request and tableView.. Whatt? Please Help

I REALLY need help. I have an app that once the userInput has been set, a network.request is sent. I Understand how to create a network request and also how to create a Table View. I just dont understand how to put the information from the network request (JSON) and insert the information I want into rows. 

Im very confused about the for loop. not sure where to place it.

please help

local composer = require( “composer” )

local scene = composer.newScene()

local widget = require(“widget”)

local json = require(“json”)

local search = require “menu”


– All code outside of the listener functions will only be executed ONCE unless “composer.removeScene()” is called.


font = “Helvetica” or native.systemFont

centerX = display.contentCenterX

centerY = display.contentCenterY

_W = display.contentWidth

_H = display.contentHeight

local resultsTable

function onRowRender(event)

local row = event.row

local id = row.index

row.bg = display.newRect( 0, 0, _W, 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( myData[id].name, 12, 0, font, 18 )

row.nameText.anchorX = 0

row.nameText.anchorY = 0.5

row.nameText:setFillColor ( 0)

row.nameText.y = 20

row.nameText.x = 42

row:insert( row.nameText )

end

return true

end


– “scene:create()”

function scene:create( event )

local function dataListener(event)

–if network event is error show alert

if event.isError then

print(“Network Error”)

else

local myData = {}

myData = json.decode(event.response)

for i = 1, #myData do

resultsTable:insertRow{

rowHeight = 50,

isCategory = false,

rowColor = {1, 1, 1},

}

end

end

return true

end

resultsTable = widget.newTableView {

top = display.statusBarHeight,

height = _H,

width = _W,

onRowRender = onRowRender,

}

    

network.request ( URL, “GET”, dataListener)

end

– “scene:show()”

function scene:show( event )

    local sceneGroup = self.view

    local phase = event.phase

    if ( phase == “will” ) then

        – Called when the scene is still off screen (but is about to come on screen).

    elseif ( phase == “did” ) then

        – Called when the scene is now on screen.

        – Insert code here to make the scene come alive.

        – Example: start timers, begin animation, play audio, etc.

    end

end

– “scene:hide()”

function scene:hide( event )

    local sceneGroup = self.view

    local phase = event.phase

    if ( phase == “will” ) then

        – Called when the scene is on screen (but is about to go off screen).

        – Insert code here to “pause” the scene.

        – Example: stop timers, stop animation, stop audio, etc.

    elseif ( phase == “did” ) then

        – Called immediately after scene goes off screen.

    end

end

– “scene:destroy()”

function scene:destroy( event )

    local sceneGroup = self.view

    – Called prior to the removal of scene’s view (“sceneGroup”).

    – Insert code here to clean up the scene.

    – Example: remove display objects, save state, etc.

end


– Listener setup

scene:addEventListener( “create”, scene )

scene:addEventListener( “show”, scene )

scene:addEventListener( “hide”, scene )

scene:addEventListener( “destroy”, scene )


return scene

You have the gist right, but you are not passing an params when you call :insertRow() so your onRowRender knows nothing about the records.  You can either use params to pass data into the tableView so onRowRender can use it, or you can use the index of the tableView row to fetch data from the data table like you are doing.

The other issue is that myData is local to your scene:create() function and your onRowRender is outside of it and can’t see myData.  You could declare it local at the top of the page and that might help.

Rob

Hey rob. I’m still very confused. I’ve used various ways of coding this. When I create a display.newText(row, (don’t know what to put here), 0, 0, font, 18)

Is there anyways you can create a sample code because everything on the forum is kinda outdated.

Also, I’m so confused on where to place the for loop. Do I place it after I create the table in scene:create or do I place it in the nerworkListener function? I’ve seen both ways and both aren’t working for me.

Can you post your current code.  Put it inside of and brackets (leave out the space after the opening [

ok so what im trying to do here is get airport info form a server and decode the table. How can I place the decoded info into tables. eg.

–json table

“delay”:“false”

–trying to place in table view

myData.[i].delay

here is my code

local json = require ( "json" ) local widget = require ( "widget" ) --------------------------------------------------------------------------------- local top = display.statusBarHeight centerX = display.contentCenterX centerY = display.contentCenterY \_W = display.contentWidth \_H = display.contentHeight local tabBarHeight = 50 local myData = {} local myList URL = "http://services.faa.gov/airport/status/LAX?format=application/json" --functions -- local myData = {} function networkListener(event) if event.isError then print("Network Error") --change into popup alert else myData = json.decode( event.response ) print ( myData ) end end local function onRowRender(event) local row = event.row local id = row.index local params = event.row.params if ( event.row.params ) then row.nameText = display.newText( params.delay, 12, 0, native.systemFont, 18 ) row.nameText.anchorX = 0 row.nameText.anchorY = 0.5 row.nameText:setFillColor( 0 ) row.nameText.y = 20 row.nameText.x = 42 row:insert( row.nameText ) end return true end myList = widget.newTableView { top = top, width = \_W, height = \_H - tabBarHeight, onRowRender = onRowRender, } for i = 1, #myData do myList:insertRow{ rowHeight = 60, isCategory = false, params = { delay = myData[i].delay } } end network.request ( URL, "GET", networkListener )

not sure if the for loop is supposed to be inside the networkListener(event) function or outside

Give this a go:

The data returned didn’t like to be parsed with the for loop, so I used pairs.  I updated the params being passed to the row creation to include both the field text, and the data from the first-level of myData.  myData also includes sub tables for status and weather, which i ignore.

local json = require ( "json" ) local widget = require ( "widget" ) --------------------------------------------------------------------------------- local top = display.statusBarHeight centerX = display.contentCenterX centerY = display.contentCenterY \_W = display.contentWidth \_H = display.contentHeight local tabBarHeight = 50 local myData = {} local myList, onrowRender URL = "http://services.faa.gov/airport/status/LAX?format=application/json" --functions -- local myData = {} local function onRowRender(event)     local row = event.row     local id = row.index     local params = event.row.params          if row.params == nil then         return     end          if ( event.row.params ) then             local nameText = display.newText( row, params.myField  .. ":" .. params.myValue , 12, 0, native.systemFont, 18 )         nameText.anchorX = 0         nameText.anchorY = 0.5         nameText:setTextColor(1,0,0, 1)         nameText.y = row.contentHeight \* 0.33         nameText.x = row.x                       end     return true end function networkListener(event)     if event.isError then         print("Network Error") --change into popup alert     else         myData = json.decode( event.response )         print ( myData )                  myList = widget.newTableView {             top = top,             width = \_W,             height = \_H - tabBarHeight,             onRowRender = onRowRender,         }                           for i,v in pairs(myData)  do             if type (v) == "table" then                 --skip sub tables             else                 myList:insertRow(                 {                     isCategory = false,                     rowHeight = 60,                     rowColor = { default={ 1, 1, 1 }, over={ 1, 0.5, 0, 0.2 } },                     lineColor = { 0.5, 0.5, 0.5 },                     params = { myField = i, myValue = v }                                      }                 )             end                                   end                       end end network.request ( URL, "GET", networkListener )

WoW thanks.  :smiley:

So is  

for i = 1, #myData do

different from

for i,v in pairs(myData) do

I heard the first one should be used?

and also, What if i wanted to single out each output into a newText object

like only myData.delay or myData.state

how would I go about doing that?

I used glider to step through the code, saw that the for loop wasn’t being entered, and changed it to a pairs loop. 

for loops using #tableName seem to work best with integer indexed tables.

Not sure what you are going after in your second Q.  Each row being rendered is being passed the params table, which has two variables (myField, myValue) which correspond to the number of fields in your myData table.

If you wanted to put all that data in one row, you wouldn’t loop over myData at all, you would set params = myData, and have params.state, params.delay, etc.  when you hit the row render function.

Play around with the code.  Set some print statements in the events, etc so you know if your variables are being populated or not.

You notice that I moved the widget creation inside the network listener, this was to ensure that data was going to be available before I tried to insert rows.  You may want to do something different if you are going to have multiple network calls :slight_smile:

Wow makes perfect sense, ok I finally get it now. Thank you!
I can finally move on with my project.

You have the gist right, but you are not passing an params when you call :insertRow() so your onRowRender knows nothing about the records.  You can either use params to pass data into the tableView so onRowRender can use it, or you can use the index of the tableView row to fetch data from the data table like you are doing.

The other issue is that myData is local to your scene:create() function and your onRowRender is outside of it and can’t see myData.  You could declare it local at the top of the page and that might help.

Rob

Hey rob. I’m still very confused. I’ve used various ways of coding this. When I create a display.newText(row, (don’t know what to put here), 0, 0, font, 18)

Is there anyways you can create a sample code because everything on the forum is kinda outdated.

Also, I’m so confused on where to place the for loop. Do I place it after I create the table in scene:create or do I place it in the nerworkListener function? I’ve seen both ways and both aren’t working for me.

Can you post your current code.  Put it inside of and brackets (leave out the space after the opening [

ok so what im trying to do here is get airport info form a server and decode the table. How can I place the decoded info into tables. eg.

–json table

“delay”:“false”

–trying to place in table view

myData.[i].delay

here is my code

local json = require ( "json" ) local widget = require ( "widget" ) --------------------------------------------------------------------------------- local top = display.statusBarHeight centerX = display.contentCenterX centerY = display.contentCenterY \_W = display.contentWidth \_H = display.contentHeight local tabBarHeight = 50 local myData = {} local myList URL = "http://services.faa.gov/airport/status/LAX?format=application/json" --functions -- local myData = {} function networkListener(event) if event.isError then print("Network Error") --change into popup alert else myData = json.decode( event.response ) print ( myData ) end end local function onRowRender(event) local row = event.row local id = row.index local params = event.row.params if ( event.row.params ) then row.nameText = display.newText( params.delay, 12, 0, native.systemFont, 18 ) row.nameText.anchorX = 0 row.nameText.anchorY = 0.5 row.nameText:setFillColor( 0 ) row.nameText.y = 20 row.nameText.x = 42 row:insert( row.nameText ) end return true end myList = widget.newTableView { top = top, width = \_W, height = \_H - tabBarHeight, onRowRender = onRowRender, } for i = 1, #myData do myList:insertRow{ rowHeight = 60, isCategory = false, params = { delay = myData[i].delay } } end network.request ( URL, "GET", networkListener )

not sure if the for loop is supposed to be inside the networkListener(event) function or outside

Give this a go:

The data returned didn’t like to be parsed with the for loop, so I used pairs.  I updated the params being passed to the row creation to include both the field text, and the data from the first-level of myData.  myData also includes sub tables for status and weather, which i ignore.

local json = require ( "json" ) local widget = require ( "widget" ) --------------------------------------------------------------------------------- local top = display.statusBarHeight centerX = display.contentCenterX centerY = display.contentCenterY \_W = display.contentWidth \_H = display.contentHeight local tabBarHeight = 50 local myData = {} local myList, onrowRender URL = "http://services.faa.gov/airport/status/LAX?format=application/json" --functions -- local myData = {} local function onRowRender(event)     local row = event.row     local id = row.index     local params = event.row.params          if row.params == nil then         return     end          if ( event.row.params ) then             local nameText = display.newText( row, params.myField  .. ":" .. params.myValue , 12, 0, native.systemFont, 18 )         nameText.anchorX = 0         nameText.anchorY = 0.5         nameText:setTextColor(1,0,0, 1)         nameText.y = row.contentHeight \* 0.33         nameText.x = row.x                       end     return true end function networkListener(event)     if event.isError then         print("Network Error") --change into popup alert     else         myData = json.decode( event.response )         print ( myData )                  myList = widget.newTableView {             top = top,             width = \_W,             height = \_H - tabBarHeight,             onRowRender = onRowRender,         }                           for i,v in pairs(myData)  do             if type (v) == "table" then                 --skip sub tables             else                 myList:insertRow(                 {                     isCategory = false,                     rowHeight = 60,                     rowColor = { default={ 1, 1, 1 }, over={ 1, 0.5, 0, 0.2 } },                     lineColor = { 0.5, 0.5, 0.5 },                     params = { myField = i, myValue = v }                                      }                 )             end                                   end                       end end network.request ( URL, "GET", networkListener )

WoW thanks.  :smiley:

So is  

for i = 1, #myData do

different from

for i,v in pairs(myData) do

I heard the first one should be used?

and also, What if i wanted to single out each output into a newText object

like only myData.delay or myData.state

how would I go about doing that?

I used glider to step through the code, saw that the for loop wasn’t being entered, and changed it to a pairs loop. 

for loops using #tableName seem to work best with integer indexed tables.

Not sure what you are going after in your second Q.  Each row being rendered is being passed the params table, which has two variables (myField, myValue) which correspond to the number of fields in your myData table.

If you wanted to put all that data in one row, you wouldn’t loop over myData at all, you would set params = myData, and have params.state, params.delay, etc.  when you hit the row render function.

Play around with the code.  Set some print statements in the events, etc so you know if your variables are being populated or not.

You notice that I moved the widget creation inside the network listener, this was to ensure that data was going to be available before I tried to insert rows.  You may want to do something different if you are going to have multiple network calls :slight_smile:

Wow makes perfect sense, ok I finally get it now. Thank you!
I can finally move on with my project.