Accessing sub tables via table.field

Despite reading dozens of forum posts, numerous tutorials and relentless attempts, I cannot figure this out. I’ve caved and thought I’d come and see if any of you are able to assist.

Simply, I’m trying to write/read a subtable but I’m struggling to make it happen. Most forum posts show the data built in the table, but mine is built on the fly.

Without trying to post masses of code, I will try to keep it succinct.

Result: Either I get nil tables, or I can’t determine how to read the subtables in a loop later as explained below.

Input : The input table being read is a JSON table. This I can read just fine. When I get to the menuItem section, I then loop through each menu item. Below is the section with the issue.

"99345681": { "itemID": 99345681, "itemType": "\_menuSimple", "nbrItems": 3, "backgroundImageLocal": "defaultAssets/bgrnd.png", "backgroundImageRemote": "", "backgroundColour": "red", "headerLoadScreenID": "", "headerImageLocal": "defaultAssets/dftButton.png", "headerImageRemote": "", "headerImageWidth": 0, "headerImageHeight": 0, "menuItem": { "1": { "iconimagelocal": "defaultAssets/dftWebIcon.png", "buttonimageremote": "", "loadScreenID": "12345681", "iconWidth": 100, "iconHeight": 100, "itemText": "Map Click", "itemFont": "native.systemFont", "itemFontSize": 16, "itemSubText": "Map Click Wheee", "itemSubFont": "native.systemFont", "itemSubFontSize": 12 }, "2": { "iconimagelocal": "defaultAssets/dftWebIcon.png", "buttonimageremote": "", "loadScreenID": "12345680", "iconWidth": 100, "iconHeight": 100, "itemText": "Web Click", "itemFont": "native.systemFont", "itemFontSize": 16, "itemSubText": "Web Click wheee", "itemSubFont": "native.systemFont", "itemSubFontSize": 12 }, "3": { "iconimagelocal": "defaultAssets/dftWebIcon.png", "buttonimageremote": "", "loadScreenID": "12345681", "iconWidth": 100, "iconHeight": 100, "itemText": "No Click", "itemFont": "native.systemFont", "itemFontSize": 16, "itemSubText": "Text on item 3", "itemSubFont": "native.systemFont", "itemSubFontSize": 12 } }

Objective:

What I *want* to do is have something like… 

I’m not going to go through ALL the different things I’ve tried, but it’s been a few! Its the table/subtable thats killing me. I think I managed to get them loaded into the table, but couldn’t figure out how to reference it again to get to the next step per below.

local \_ms = {} \_ms.menuItem={} \*note: tbl = the JSON shown above. for k, v in pairs( tbl ) do -- This works if k=="menuItem" then -- This works for items=1,\_ms.nbrItems do -- This works for m, i in pairs( tbl["menuItem"][tostring(items)] ) do -- This works \_ms.menuItem[#\_ms.menuItem+1].m=i -- This is the bit I can't figure out -- So I can refer to it later as... -- button[1].label = \_ms.menuItem[1].itemText -- button[1].image = \_ms.menuItem[1].iconimagelocal -- button[2].label = \_ms.menuItem[2].itemText -- button[2].label = \_ms.menuItem[2].iconimagelocal end end end

 Later in another module I will have the below. (I’ll extrapolate to fix the remaining fields once one is working). The purpose being that I construct the button solely from JSON input.

           

 button[i].label = display.newText( \_ms.menuItem[i].itemText, \_ms.menuItem[i].width, \_ms.menuItem[i].y,\_ms.menuItem[i].font,\_ms.menuItem[i].fontSize)

Extra fluff:

I AM aware of print_r and I’ve used it to prove that I was able to load the table somewhat, but I end up confusing myself at times. I also used the debugger to monitor on the fly to figure out where I was overwriting. Much of my later results was loading the table, but not incrementing it, which is why I’m currently at the ‘+1’ stage.

For the JSON above the menuItem, that works just fine as I use code similar to…

 if (k=="backgroundImageLocal") then             if v=="" then -- Set default or print error if needed             else                 \_ms.backgroundImageLocal = v end end -- Later I used bgrnd = display.newImageRect(\_ms.backgroundImageLocal, display.actualContentWidth , display.actualContentHeight ) with success

I just need to be able to handle items where we have 1 to X number of menu items and be able to process them.

Appreciate any help you can offer. Tables are SUCH a pain when I get more complex with them :slight_smile:

Thank you

I will add that this topic was close, but I still didn’t get it.

https://forums.coronalabs.com/topic/62356-get-subtable-from-module-table/

Edit; 

Per this example I need more like stuff.options[1].text :slight_smile:

I think what you need to do is:

[lua]

_ms.menuItem[#_ms.menuItem+ 1] = {}

[/lua]

Before you try and assign anything to it. You’re trying to access/set the .m (or .label, .image) field on something that isn’t yet a table. Each new level in the table has to be defined first.

That didn’t seem to do it - might be part of the puzzle though.

What is happening then? Do you get any errors?

If I use

                _ms.menuItem[#_ms.menuItem+1] = {}

                _ms.menuItem[#_ms.menuItem+1].m = i

I get an attempt to index field ‘?’ (a nil value)

If I use

                _ms.menuItem[items] = {}

                _ms.menuItem[items] = m,i

                common.print_r(_ms.menuItem)

the print_r gives me nil

As I read each item, I can see this in the pairs loop using        print( “Item:”…items…" MenuItem:"…m…" Value:"…i )

Jul 21 11:53:31.720: Item:1 MenuItem:itemSubText Value:Map Click Wheee

Jul 21 11:53:31.720: Item:1 MenuItem:iconWidth Value:100

Jul 21 11:53:31.720: Item:1 MenuItem:itemFont Value:native.systemFont

Jul 21 11:53:31.720: Item:1 MenuItem:buttonimageremote Value:

Jul 21 11:53:31.720: Item:1 MenuItem:itemFontSize Value:16

Jul 21 11:53:31.720: Item:1 MenuItem:iconHeight Value:100

Jul 21 11:53:31.720: Item:1 MenuItem:itemSubFontSize Value:12

Jul 21 11:53:31.720: Item:1 MenuItem:itemSubFont Value:native.systemFont

Jul 21 11:53:31.720: Item:1 MenuItem:itemText Value:Map Click

Jul 21 11:53:31.721: Item:1 MenuItem:iconimagelocal Value:defaultAssets/dftWebIcon.png

Trying to reference it like _ms.menuItem[1].loadScreenID give me a ‘attempt to index field ‘?’ (a nil value)’

Ah!

Once you’ve done:

[lua]

_ms.menuItem[#_ms.menuItem+1] = {}

[/lua]

Then to access this table, you now use:

[lua]

_ms.menuItem[#_ms.menuItem].m = i   – no longer need to use +1 as this table is now the last item in the _ms.menuItem table, not the hypothetical ‘next’ one.

[/lua]

It’s the same as doing:

[lua]

local tables = {}

tables[1] = {}

tables[1].m = i

[/lua]

Whereas you were doing:

[lua]

local tables = {}

tables[1] = {}

tables[2].m = i

[/lua]

OK, progress I think, but still not there…

if (m=="loadScreenID") then \_ms.menuItem[#\_ms.menuItem].loadScreenID = i -- This seems OK as the print is OK common.print\_r(\_ms.menuItem) -- This still always prints nil - it should print the table? print( "Item:"..\_ms.menuItem[#\_ms.menuItem].loadScreenID ) -- This prints the right value.

in the next set of statements I have

 if (m=="itemText") then \_ms.menuItem[#\_ms.menuItem].itemText = i end

As I iterate through the table, it will come here earlier/later during the pairs cycle.

print( (\_ms.menuItem[1].loadScreenID).."\<\<\<" ) print( (\_ms.menuItem[1].itemText).."\<\<\<" )

The first line works, the second one fails. (which is why I hoped the print_r would work so I can see what the table looks like.

(Later I will cycle through this table and set button properties per the first post)
 

OK, finally success!

Huge shoutout to Nick for getting me there, it’s been driving me nuts!  Your answer is the missing link. and when I mixed up some of my other stuff I was able to get it to work.

For reference if some other poor soul arrives at this thread, here’s the final code that works…

 if k=="menuItem" then for items=1,\_ms.nbrItems do for m, i in pairs( tbl["menuItem"][tostring(items)] ) do \_ms.menuItem[#\_ms.menuItem+1] = {} if (m=="loadScreenID") then \_ms.menuItem[items].loadScreenID = i end \<snip\> \<snip\> for i = 1, \_ms.nbrItems do button[i].label = display.newText( \_ms.menuItem[i].itemText, button[i].width+10, button[i].y-15,native.systemFont,16) end

THANK YOU so much Nick!

I will add that this topic was close, but I still didn’t get it.

https://forums.coronalabs.com/topic/62356-get-subtable-from-module-table/

Edit; 

Per this example I need more like stuff.options[1].text :slight_smile:

I think what you need to do is:

[lua]

_ms.menuItem[#_ms.menuItem+ 1] = {}

[/lua]

Before you try and assign anything to it. You’re trying to access/set the .m (or .label, .image) field on something that isn’t yet a table. Each new level in the table has to be defined first.

That didn’t seem to do it - might be part of the puzzle though.

What is happening then? Do you get any errors?

If I use

                _ms.menuItem[#_ms.menuItem+1] = {}

                _ms.menuItem[#_ms.menuItem+1].m = i

I get an attempt to index field ‘?’ (a nil value)

If I use

                _ms.menuItem[items] = {}

                _ms.menuItem[items] = m,i

                common.print_r(_ms.menuItem)

the print_r gives me nil

As I read each item, I can see this in the pairs loop using        print( “Item:”…items…" MenuItem:"…m…" Value:"…i )

Jul 21 11:53:31.720: Item:1 MenuItem:itemSubText Value:Map Click Wheee

Jul 21 11:53:31.720: Item:1 MenuItem:iconWidth Value:100

Jul 21 11:53:31.720: Item:1 MenuItem:itemFont Value:native.systemFont

Jul 21 11:53:31.720: Item:1 MenuItem:buttonimageremote Value:

Jul 21 11:53:31.720: Item:1 MenuItem:itemFontSize Value:16

Jul 21 11:53:31.720: Item:1 MenuItem:iconHeight Value:100

Jul 21 11:53:31.720: Item:1 MenuItem:itemSubFontSize Value:12

Jul 21 11:53:31.720: Item:1 MenuItem:itemSubFont Value:native.systemFont

Jul 21 11:53:31.720: Item:1 MenuItem:itemText Value:Map Click

Jul 21 11:53:31.721: Item:1 MenuItem:iconimagelocal Value:defaultAssets/dftWebIcon.png

Trying to reference it like _ms.menuItem[1].loadScreenID give me a ‘attempt to index field ‘?’ (a nil value)’

Ah!

Once you’ve done:

[lua]

_ms.menuItem[#_ms.menuItem+1] = {}

[/lua]

Then to access this table, you now use:

[lua]

_ms.menuItem[#_ms.menuItem].m = i   – no longer need to use +1 as this table is now the last item in the _ms.menuItem table, not the hypothetical ‘next’ one.

[/lua]

It’s the same as doing:

[lua]

local tables = {}

tables[1] = {}

tables[1].m = i

[/lua]

Whereas you were doing:

[lua]

local tables = {}

tables[1] = {}

tables[2].m = i

[/lua]

OK, progress I think, but still not there…

if (m=="loadScreenID") then \_ms.menuItem[#\_ms.menuItem].loadScreenID = i -- This seems OK as the print is OK common.print\_r(\_ms.menuItem) -- This still always prints nil - it should print the table? print( "Item:"..\_ms.menuItem[#\_ms.menuItem].loadScreenID ) -- This prints the right value.

in the next set of statements I have

 if (m=="itemText") then \_ms.menuItem[#\_ms.menuItem].itemText = i end

As I iterate through the table, it will come here earlier/later during the pairs cycle.

print( (\_ms.menuItem[1].loadScreenID).."\<\<\<" ) print( (\_ms.menuItem[1].itemText).."\<\<\<" )

The first line works, the second one fails. (which is why I hoped the print_r would work so I can see what the table looks like.

(Later I will cycle through this table and set button properties per the first post)
 

OK, finally success!

Huge shoutout to Nick for getting me there, it’s been driving me nuts!  Your answer is the missing link. and when I mixed up some of my other stuff I was able to get it to work.

For reference if some other poor soul arrives at this thread, here’s the final code that works…

 if k=="menuItem" then for items=1,\_ms.nbrItems do for m, i in pairs( tbl["menuItem"][tostring(items)] ) do \_ms.menuItem[#\_ms.menuItem+1] = {} if (m=="loadScreenID") then \_ms.menuItem[items].loadScreenID = i end \<snip\> \<snip\> for i = 1, \_ms.nbrItems do button[i].label = display.newText( \_ms.menuItem[i].itemText, button[i].width+10, button[i].y-15,native.systemFont,16) end

THANK YOU so much Nick!