After cloning a GUI structure, how can I pass data to its script?

I’m making a generic billboard GUI, which will get re-used by multiple pieces of furniture in the game. The player interacts with a Prox, whose Local Script (1) Clones the Options GUI. (2) Passes it a list of customized options. (3) It then shows itself. (4) Invoke callbacks from those options.

I can’t work out how to do step (2): Passing the data to the cloned script from a different Local Script. In the billboard is a localScript:

function setup(pTitle:string, pOptions, pCallback)
   script.Parent.frame.lblTitle.Text = pTitle
   -- sets up the list of clickable options in an autosize frame
   -- selected options invoke a callback(optionId)
   -- all good, all easy, all tested in the Workspace
   -- How do I CALL this function after cloning its parent?
end

I tested the script on a fixed GUI on a Billboard in Workspace, and now its all moved to PlayerStarterGui and hidden, ready to be cloned. But after cloning, how do I ‘call’ its functions in its script, or otherwise, pass data to it?

local lBillboard = plrGui.optionsTemplate:Clone() -- Cloned.
lBillboard.script.Disabled = false
-- Now, pass it the information it needs:
lBillboard.setup ("Title", {option1,option2}, myCallback) --HOW?
lBillboard.parent = plrGui

Obviously, there is no such thing as .setup() , this is just as example of what I would do next, if I could find a way.

Using a Module Script works, but something about this is worrying me!

local lBillboard = plrGui.optionsTemplate:Clone() – Cloned.
local lBBModule = require(lBillboard.mScript)
lBBModule .setup(“title”) – yay

Although it works… I’m worried that this is weird and/or bad practice. I’ve not seen any other forum posts or examples that do this kind of thing!

I can’t use an event, because, each time I clone it, all the resultant GUIs will be listening to the same event, and I won’t be able to target a particular one.

I’m trying to make it self-contained, so that the script and the billboard can all be together, so it’s easy to copy it all from project-to-project in the future.

An alternative is to create the whole billboard & GUI elements purely in code. But it’s a LOT to write out and difficult to do design changes without physically looking at it.

There’s no other posts about this, which makes me think my entire approach is wrong! What’s the right approach?

you can make a setup function but use the gui to reference instead of script

for example:

--originally
function setup()
  script.Parent.TextLabel.Text = "asdf"
end

--new
function setup(gui)
  gui.TextLabel.Text = "asdf"
end

then clone the ui and call setup(ui)

you can simply have a separate event inside of every single “containment” object

1 Like

Thanks. I like the way your icon is like a better version of mine!

I don’t need to pass the gui as reference; here’s what it looks like in full:

local mFr = script.Parent.Fr -- the frame that contains the functional GUI elements
local m = {}                 -- anything that starts with an 'm' is a module-wide variable

function m.setup(pTitle:string,pOptions,pDesc)
	mFr.txtTitle.Text = (pTitle or "") -- because all the GUI elements are children, there's no need to pass a reference to GUI as a parameter
	mFr.txtDesc.Text = (pDesc or "")
	for _,opt in pairs(pOptions) do
		local lFr = mFr.template:Clone() -- copy the template option (frame, img, border, txtLbl)
        -- <snip> image setup
		lFr.TxtBtn.Text = opt.text  -- Set the principal text that tells the user what this option is
        -- <snip> the :Connect for the callback -- call the callback and pass the Option (which could have .id fields or whatever the caller wants, to identify which one was clicked)
		lFr.Visible = true -- the mFr.template is invisible (in case it accidentally gets left in)
		lFr.Parent = mFr
	end
	
	mFr.template:Destroy() -- This was only there temporarily, to copy, so I can design it
end

return m

Note that this all works well, the question is… what’s the best way to handle it all? I’m doing this:

local lBillboard = plrGui.optionsTemplate:Clone() – Cloned.
local lBBModule = require(lBillboard.mScript)
lBBModule .setup(“title”) – yay

… but it is worrying me; I haven’t seen this kind of created-on-the-fly Module Script used in other solutions. Once the GUI object is destroyed, the reference to it should get destroyed and it should get trash collected. Is there anything which would mean this is causing a memory leak?

I really wish there was a way to directly call a function in a script, without the boilerplate code.

By having an Event as a child of the GUI? Do they work there? I’ve only used them as members of the top-level storage folders (StartPlayerScripts, etc). Interesting, so then, after cloning, I can do:

local lBillboard = plrGui.optionsTemplate:Clone() – Cloned.
lBillboard.setupEvent:Fire(params)

Something like that? And then in the local script inside the GUI’s main script, have a listener?

yep, exactly like that. events can be parented anywhere

1 Like