display name of inventory item

Godot Version

4.3

Question

So I am a beginner to game development in general and just trying to figure things out. I am trying to make an inventory system. I have the inventory backend set up pretty well I think but trying to set up a UI is making me feel crazy.

I am creating buttons dynamically by using a template button, based on what is currently in the player inventory and adding an image to the button. This works fine. I also add the item id of the current item into the button’s meta data. Then I want to be able to click the created buttons to print the name of the item.

I cannot figure out how to access the button’s metadata. Every time I try the output is null. I think I figured out that the self end up referring to the parent control node, but I do not know why. The item id prints correctly when I am creating the buttons and I can see the metadata has been added when I play the game scene.

The hierarchy is a control node, nine patch rect, grid container, button and then texture rect.

Any help would be appreciated, thank you!

extends Control

@onready var grid = $NinePatchRect/GridContainer
@onready var inventory = null

@onready var template = $NinePatchRect/GridContainer/Button
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	inventory = InventoryPlayer.inventory


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	pass

func populate_inventory():
	for child in grid.get_children():
		grid.remove_child(child)
		child.queue_free()
	for category in inventory.keys():
		for item_id in inventory[category].keys():
			var item_data = inventory[category][item_id]
			var button = template.duplicate()
			var button_img = button.get_node("TextureRect")
			button.visible = true
			button_img.texture = load("res://icon.svg")
			button.set_meta("item_id", item_id)
			print(button.get_meta("item_id"))
			grid.add_child(button)

func _on_button_pressed() -> void:
	print(self.get_meta("item_id"))

extends Control

@onready var grid = $NinePatchRect/GridContainer
@onready var inventory = null
@onready var template = $NinePatchRect/GridContainer/Button

func _ready() → void:
inventory = InventoryPlayer.inventory

func populate_inventory():
# Clear existing buttons
for child in grid.get_children():
grid.remove_child(child)
child.queue_free()

# Create new buttons for each item
for category in inventory.keys():
    for item_id in inventory[category].keys():
        var item_data = inventory[category][item_id]
        var button = template.duplicate()
        var button_img = button.get_node("TextureRect")
        button.visible = true
        button_img.texture = load("res://icon.svg")
        button.set_meta("item_id", item_id)
        # Connect the button's pressed signal to a method that passes the button itself
        button.pressed.connect(_on_inventory_button_pressed.bind(button))
        grid.add_child(button)

New method that receives the specific button instance

func _on_inventory_button_pressed(button: Button) → void:
var item_id = button.get_meta(“item_id”)
print("Clicked item: ", item_id)