Code issues - TextLabel cloned not found issues

I’m encountering an issue when try to destroy the cloned frame (created from the server) on the client side. Output show me this below, What could be wrong with my code? :pray:

project organization:
image

server-side script:

local clonedTemplateEvent = game:GetService("ReplicatedStorage").orderTemplate:WaitForChild("clonedTemplateEvent")

clonedTemplateEvent.OnServerEvent:Connect(function(player, username, item1, item2, totalPrice, newFormatText)
	local frameTemplate = game:GetService("ReplicatedStorage").orderTemplate.Template

	-- Format the text for the textLabel
	local formattedText

	if item1 and item2 and item2 ~= "" then
		formattedText = "Order by " .. username .. ": " .. item1 .. " and " .. item2 .. ". Your earnings: $" .. totalPrice .. " CB"
	elseif item1 then
		formattedText = "Order by " .. username .. ": " .. item1 .. ". Your earnings: $" .. totalPrice .. " CB"
	else
		warn("No items provided for the order.")
		return
	end

	-- Loop through all players
	for _, plr in ipairs(game.Players:GetPlayers()) do
		if plr.Team and plr.Team.Name == "Chef" then
			-- Clone the frameTemplate into the ScrollingFrame
			local OrdersList_UI = plr:WaitForChild("PlayerGui"):FindFirstChild("OrdersList_UI")
			OrdersList_UI.Enabled = true

			local clonedFrame = frameTemplate:Clone()
			clonedFrame.Parent = OrdersList_UI.Background.ScrollingFrame

			-- Update the textLabel with formatted text
			clonedFrame.TextLabel.Text = formattedText
		else
			warn("Player is not in Chef Team.")
		end
	end

	-- Assign the newFormatText variable to formattedText before firing to clients
	newFormatText = formattedText
	-- Fire the clonedTemplateEvent to the client with the newFormatText
	clonedTemplateEvent:FireAllClients(player, newFormatText)
end)

localscript (when press deliver button):

local orderUpdateEvent = game:GetService("ReplicatedStorage").remoteEvents:WaitForChild("OrderUpdateEvent")

local orders = {}

-- Listen to the remote event to receive order update notifications
orderUpdateEvent.OnClientEvent:Connect(function(orderData)
	-- Update the client's UI with the new order data
	table.insert(orders, orderData)  -- Add the order to the local orders table
end)

local function removeOrderAndUI(orderToRemove)
	if not orderToRemove then
		warn("Order data is nil.")
		return
	end

	-- Check if the order data has the necessary properties
	if not orderToRemove.username or not orderToRemove.formattedText then
		warn("Invalid order data structure. Missing properties.")
		return
	end
	
	print(orderToRemove.formattedText)

	-- Get the local player and their PlayerGui
	local player = game.Players.LocalPlayer
	local playerGui = player:FindFirstChild("PlayerGui")
	if playerGui then
		local OrdersList_UI = playerGui:FindFirstChild("OrdersList_UI")
		if OrdersList_UI then
			local scrollingFrame = OrdersList_UI.Background:FindFirstChild("ScrollingFrame")
			if scrollingFrame then				
				-- Find and remove the TextLabel associated with the order from the UI
				for _, frame in ipairs(scrollingFrame:GetChildren()) do
					local textLabel = frame:FindFirstChild("TextLabel")
					if textLabel then
						if textLabel.Text == orderToRemove.formattedText then
							frame:Destroy()
							print("TextLabel destroyed successfully.")
							break
						end
					else
						warn("TextLabel not found in frame:", frame.Name)
					end
				end

				-- Remove the delivered order from the orders table
				for i, order in ipairs(orders) do
					if order == orderToRemove then
						table.remove(orders, i)
						print("Order removed from orders table.")
						break
					end
				end

				-- Print a message indicating successful removal
				print("Order successfully removed from orders table and UI.")
			else
				warn("ScrollingFrame not found.")
			end
		else
			warn("OrdersList_UI not found.")
		end
	else
		warn("PlayerGui not found.")
	end
end

-- Function to check nearby customer
local function checkNearbyCustomer()
	-- Check if there is a customer nearby and return their username if found
	local maxDistance = 15 -- Maximum distance to consider a player as nearby (adjust as needed)
	local player = game.Players.LocalPlayer
	local nearbyCustomer = ""

	for _, otherPlayer in ipairs(game.Players:GetPlayers()) do
		if otherPlayer ~= player and otherPlayer.Team.Name == "Customer" then
			local character = otherPlayer.Character
			if character and character:FindFirstChild("HumanoidRootPart") then
				local distance = (character.HumanoidRootPart.Position - player.Character.HumanoidRootPart.Position).magnitude
				if distance <= maxDistance then
					nearbyCustomer = otherPlayer.Name -- Set the nearby customer username
					break
				end
			end
		end
	end

	return nearbyCustomer
end

-- Function to check if the order exists in the orders table
local function checkOrderExists(username)
	-- Check if an order exists for a given username
	print("Checking if order exists for username:", username)
	for _, order in pairs(orders) do
		if order.username == username then
			print("Order found for username:", username)
			return true -- Order found
		end
	end
	print("Order not found for username:", username)
	return false -- Order not found
end

local deliverOrderFunction = game:GetService("ReplicatedStorage").remoteFunctions.deliverOrderFunction
local orderButton = script.Parent

orderButton.MouseButton1Click:Connect(function(player)  
	print("Delivery order button pressed")

	print(orders)

	-- Obtain the name of the nearby user
	local nearbyCustomer = checkNearbyCustomer()
	if nearbyCustomer == "" then
		print("No nearby customer found.")
		return
	end

	-- Check if there is an order for the nearby user
	local orderExistsForCustomer = checkOrderExists(nearbyCustomer)

	if orderExistsForCustomer then
		-- Get the order for the nearby user
		local orderData = nil
		local index = nil
		for i, order in ipairs(orders) do
			if order.username == nearbyCustomer then
				orderData = order
				index = i -- Store the index
				break
			end
		end

		if orderData then
			-- Print the order data before processing
			print("Order data before delivery:")
			for key, value in pairs(orderData) do
				print(key, value)
			end

			-- Check if orderData is valid before invoking deliverOrderFunction
			if not orderData.username or not orderData.item1 or not orderData.item2 or not orderData.totalprice then
				warn("Invalid order data")
				return
			end

			-- Call deliverOrderFunction with orderData and index
			print("Calling deliverOrderFunction with orderData and index:", orderData, index)
			if orderData and index then
				-- Get the RemoteFunction for delivering orders from the client
				local success, errorMessage = deliverOrderFunction:InvokeServer(orderData)
				if success then
					print("Order delivery successful.")

					-- Update any UI or data related to the removed order here
					local OrderReceivedByCustomer_UI = game.Players.LocalPlayer.PlayerGui:WaitForChild("OrderReceivedByCustomer_UI")
					OrderReceivedByCustomer_UI.Enabled = true
					OrderReceivedByCustomer_UI.ReceivedByCustomer_TextLabel.Text = "Order Received by ".. nearbyCustomer ..". + $".. orderData.totalprice .." CB"

					wait(3)
					OrderReceivedByCustomer_UI.Enabled = false
					wait(.2)

					-- Remove the delivered order from orders table and UI
					removeOrderAndUI(orderData)

					-- Print a message indicating successful removal
					print("Order successfully removed from orders table. Index:", index)
				else
					print("Failed to deliver order:", errorMessage)
				end
			else
				warn("Order data or index is missing or nil")
			end
		else
			print("Failed to find order data for nearby customer:", nearbyCustomer)
		end
	else
		print("No order found for nearby customer:", nearbyCustomer)
	end
end)

Here you are looping through all the Children of the scrollingFrame. It will print textlabel not found for every child that doesn’t have a textlabel until a textlabel is found. One of the children is a UIListLayout.

If you are just looking for the first TextLabel descendant of ScrollingFrame, there is an easy way to do it.

local textLabel = scrollingFrame:FindFirstChild("TextLabel",true)

by putting “true” as the second argument you are searching through all the descendants of scrollingFrame, not just the children.

1 Like

It works! Thank you! but there’s a problem, the orderToRemove.formattedText has nothing, it’s empty, and in the comparison if textLabel.Text == orderToRemove.formattedText then it fails because it’s empty, what can I do to fix that? :confused:

local function removeOrderAndUI(orderToRemove)
	if not orderToRemove then
		warn("Order data is nil.")
		return
	end

	-- Check if the order data has the necessary properties
	if not orderToRemove.username or not orderToRemove.formattedText then
		warn("Invalid order data structure. Missing properties.")
		return
	end

	-- Get the local player and their PlayerGui
	local player = game.Players.LocalPlayer
	local playerGui = player:FindFirstChild("PlayerGui")
	if playerGui then
		local OrdersList_UI = playerGui:FindFirstChild("OrdersList_UI")
		if OrdersList_UI then
			local scrollingFrame = OrdersList_UI.Background:FindFirstChild("ScrollingFrame")
			if scrollingFrame then				
				-- Find and remove the TextLabel associated with the order from the UI
				for _, frame in ipairs(scrollingFrame:GetChildren()) do
					local textLabel = scrollingFrame:FindFirstChild("TextLabel",true)
					if textLabel then
						if textLabel.Text == orderToRemove.formattedText then
							frame:Destroy()
							print("TextLabel destroyed successfully.")
							break
						end
					else
						warn("TextLabel not found in frame:", frame.Name)
					end
				end

				-- Remove the delivered order from the orders table
				for i, order in ipairs(orders) do
					if order == orderToRemove then
						table.remove(orders, i)
						print("Order removed from orders table.")
						break
					end
				end

				-- Print a message indicating successful removal
				print("Order successfully removed from orders table and UI.")
			else
				warn("ScrollingFrame not found.")
			end
		else
			warn("OrdersList_UI not found.")
		end
	else
		warn("PlayerGui not found.")
	end
end

Make sure formattedText is not nil. If there’s a possibility of formattedText being nil and you want an empty string to show up then you can account for that.

textlabel.Text = orderToRemove.formattedText and orderToRemove.formattedText or ""

this is a fancy tertiary statement that is identical to:

if orderToRemove.formattedText then
    textLabel.Text = orderToRemove.formattedText
else
    textLabel.Text = ""
end

Ah, I’ve found the issue. It’s that when the value of the field newFormatText is updated on the server, it doesn’t update correctly in the LocalScript, which is why it’s empty. How can I fix that error?

server:

local clonedTemplateEvent = game:GetService("ReplicatedStorage").orderTemplate:WaitForChild("clonedTemplateEvent")

clonedTemplateEvent.OnServerEvent:Connect(function(player, username, item1, item2, totalPrice, newFormatText)
	local frameTemplate = game:GetService("ReplicatedStorage").orderTemplate.Template

	-- Format the text for the textLabel
	local formattedText

	if item1 and item2 and item2 ~= "" then
		formattedText = "Order by " .. username .. ": " .. item1 .. " and " .. item2 .. ". Your earnings: $" .. totalPrice .. " CB"
	elseif item1 then
		formattedText = "Order by " .. username .. ": " .. item1 .. ". Your earnings: $" .. totalPrice .. " CB"
	else
		warn("No items provided for the order.")
		return
	end

	-- Loop through all players
	for _, plr in ipairs(game.Players:GetPlayers()) do
		if plr.Team and plr.Team.Name == "Chef" then
			-- Clone the frameTemplate into the ScrollingFrame
			local OrdersList_UI = plr:WaitForChild("PlayerGui"):FindFirstChild("OrdersList_UI")
			OrdersList_UI.Enabled = true

			local clonedFrame = frameTemplate:Clone()
			clonedFrame.Parent = OrdersList_UI.Background.ScrollingFrame

			-- Update the textLabel with formatted text
			clonedFrame.TextLabel.Text = formattedText
		else
			warn("Player is not in Chef Team.")
		end
	end

	-- Assign the newFormatText variable to formattedText before firing to clients
	newFormatText = formattedText
	-- Fire the clonedTemplateEvent to the client with the newFormatText
	clonedTemplateEvent:FireAllClients(player, newFormatText)
end)

localscript:

-- Define the orders table if it doesn't exist
local orders = {}

-- Function to get order data when buttonYesRequestOrder is pressed
local function saveOrderData()
	-- Gather information about the selected items and calculate total cost
	local selectedItems = {}
	for _, button in ipairs(clickedButtons) do
		local itemName = buttonNames[button.Name]
		if itemName then
			table.insert(selectedItems, itemName)
		end
	end
	local totalCost = calculateTotalPrice()

	-- Create the order object
	local order = {
		username = Players.LocalPlayer.Name, -- Include the username of the player
		item1 = selectedItems[1] or "",
		item2 = selectedItems[2] or "",
		totalprice = totalCost,
		formattedText = ""
	}

	-- Add the order to the orders table
	table.insert(orders, order)

	-- Notify the server about the new order
	orderUpdateEvent:FireServer(order)

	return order -- Return the order table
end

I’m guessing you want to just fire it to one client. So use:

clonedTemplateEvent:FireClient(player, newFormatText)

FireAllClients doesn’t take a player as the first argument so in your code the player argument gets passed on as the first argument and newFormatText is the second argument.

I don’t see the code where you listen for this event. Obviously once you pick it up on the client you have to handle it and everything.

It still doesn’t work, something strange is happening, and the field is not updating. I’ll share the complete script with you. I want the formattedText field in my orders table to be updated (update formattedText field server to client), which you can see here:

-- Define the orders table if it doesn't exist
local orders = {}

-- Function to get order data when buttonYesRequestOrder is pressed
local function saveOrderData()
	-- Gather information about the selected items and calculate total cost
	local selectedItems = {}
	for _, button in ipairs(clickedButtons) do
		local itemName = buttonNames[button.Name]
		if itemName then
			table.insert(selectedItems, itemName)
		end
	end
	local totalCost = calculateTotalPrice()

	-- Create the order object
	local order = {
		username = Players.LocalPlayer.Name, -- Include the username of the player
		item1 = selectedItems[1] or "",
		item2 = selectedItems[2] or "",
		totalprice = totalCost,
		formattedText = ""
	}

	-- Add the order to the orders table
	table.insert(orders, order)

	-- Notify the server about the new order
	orderUpdateEvent:FireServer(order)

	return order -- Return the order table
end

server script:

local clonedTemplateEvent = game:GetService("ReplicatedStorage").orderTemplate:WaitForChild("clonedTemplateEvent")

clonedTemplateEvent.OnServerEvent:Connect(function(player, username, item1, item2, totalPrice, newFormatText)
	local frameTemplate = game:GetService("ReplicatedStorage").orderTemplate.Template

	-- Format the text for the textLabel
	local formattedText

	if item1 and item2 and item2 ~= "" then
		formattedText = "Order by " .. username .. ": " .. item1 .. " and " .. item2 .. ". Your earnings: $" .. totalPrice .. " CB"
	elseif item1 then
		formattedText = "Order by " .. username .. ": " .. item1 .. ". Your earnings: $" .. totalPrice .. " CB"
	else
		warn("No items provided for the order.")
		return
	end

	-- Loop through all players
	for _, plr in ipairs(game.Players:GetPlayers()) do
		if plr.Team and plr.Team.Name == "Chef" then
			-- Clone the frameTemplate into the ScrollingFrame
			local OrdersList_UI = plr:WaitForChild("PlayerGui"):FindFirstChild("OrdersList_UI")
			OrdersList_UI.Enabled = true

			local clonedFrame = frameTemplate:Clone()
			clonedFrame.Parent = OrdersList_UI.Background.ScrollingFrame

			-- Update the textLabel with formatted text
			clonedFrame.TextLabel.Text = formattedText
		else
			warn("Player is not in Chef Team.")
		end
	end
	
	newFormatText = formattedText
	
	clonedTemplateEvent:FireAllClients(newFormatText)

end)

localscript:

-- Import necessary services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

-- Get the remote event for updating orders
local orderUpdateEvent = ReplicatedStorage.remoteEvents:WaitForChild("OrderUpdateEvent")

-- Get the player's GUI
local playerGui = Players.LocalPlayer:WaitForChild("PlayerGui")

-- Find the button within the PlayerGui hierarchy
local deliveryOrderButton = playerGui:WaitForChild("Order_Delivery"):WaitForChild("deliveryOrderButton")
local orderTextInfo = playerGui:WaitForChild("Order_Delivery").orderTextInfo

-- Define variables
local buttonsFolder = script.Parent
local hideGuiButton = buttonsFolder.Parent.OrderFrame.NoTextButton
local totalCostTextLabel = buttonsFolder.Parent.OrderFrame.TotalCostText
local buttonYesRequestOrder = buttonsFolder.Parent.OrderFrame.YesTextButton
local textOrdersNames = {
	buttonsFolder.Parent.OrderFrame.OrderName1Text,
	buttonsFolder.Parent.OrderFrame.OrderName2Text
}
local clickedButtons = {}

-- Define buttons and their associated names
local buttonNames = {
	BurgerTextButton = "Burger",
	DonutTextButton = "Donut",
	FriesTextButton = "Fries",
	SliceOfCakeTextButton = "Slice of Cake",
	SodaTextButton = "Soda",
	WaterTextButton = "Water"
}

-- Define prices for each button
local buttonPrices = {
	BurgerTextButton = 5,
	DonutTextButton = 3,
	FriesTextButton = 4,
	SliceOfCakeTextButton = 6,
	SodaTextButton = 2,
	WaterTextButton = 1
}

-- Function to toggle loading order sent GUI
local function toggleLoadingOrderSent(enabled)
	-- Toggle the loading order sent GUI visibility
	Players.LocalPlayer.PlayerGui.loading_order_sent.Enabled = enabled
end

-- Function to update order name displayed
local function updateOrderName(button, index)
	-- Update the displayed order name based on the button clicked
	local orderNameText = textOrdersNames[index]
	if orderNameText then
		orderNameText.Text = button.Text
	end
end

-- Function to calculate total price of selected items
local function calculateTotalPrice()
	-- Calculate the total price of selected items
	local totalPrice = 0
	for _, clickedButton in ipairs(clickedButtons) do
		local price = buttonPrices[clickedButton.Name]
		totalPrice = totalPrice + price
	end
	return totalPrice
end

-- Connect click events for each button
for _, button in pairs(buttonsFolder:GetChildren()) do
	if button:IsA("TextButton") then
		-- Connect click events for each button to handle order selection
		button.MouseButton1Click:Connect(function()
			if #clickedButtons < 2 then
				table.insert(clickedButtons, button)
				updateOrderName(button, #clickedButtons)
				totalCostTextLabel.Text = "Total Cost: $" .. calculateTotalPrice()
				-- Change button background color to green to indicate selection
				button.BackgroundColor3 = Color3.fromRGB(0, 255, 0) -- Green color
			end
		end)
	end
end

-- Function to reset button color
local function resetButtonColor()
	-- Reset the color of all buttons to their original color
	for _, button in ipairs(buttonsFolder:GetChildren()) do
		if button:IsA("TextButton") then
			button.BackgroundColor3 = Color3.fromRGB(211, 211, 211) -- Original color
		end
	end
end

-- Function to reset the order
local function resetOrder()
	-- Reset the order selection and displayed information
	clickedButtons = {}
	for _, orderNameText in ipairs(textOrdersNames) do
		orderNameText.Text = "..."
	end
	totalCostTextLabel.Text = "Total Cost: $0"
end

-- Connect click event for hide GUI button
hideGuiButton.MouseButton1Click:Connect(function()
	-- Reset the order and hide the GUI
	resetOrder()
	ReplicatedStorage.remoteEvents:WaitForChild("close_OrderGUI"):FireServer()
	resetButtonColor() -- Reset button color
end)

-- Define the orders table if it doesn't exist
local orders = {}

-- Function to get order data when buttonYesRequestOrder is pressed
local function saveOrderData()
	-- Gather information about the selected items and calculate total cost
	local selectedItems = {}
	for _, button in ipairs(clickedButtons) do
		local itemName = buttonNames[button.Name]
		if itemName then
			table.insert(selectedItems, itemName)
		end
	end
	local totalCost = calculateTotalPrice()

	-- Create the order object
	local order = {
		username = Players.LocalPlayer.Name, -- Include the username of the player
		item1 = selectedItems[1] or "",
		item2 = selectedItems[2] or "",
		totalprice = totalCost,
		formattedText = ""
	}

	-- Add the order to the orders table
	table.insert(orders, order)

	-- Notify the server about the new order
	orderUpdateEvent:FireServer(order)

	return order -- Return the order table
end

-- Function to check nearby customer
local function checkNearbyCustomer()
	-- Check if there is a customer nearby and return their username if found
	local maxDistance = 15 -- Maximum distance to consider a player as nearby (adjust as needed)
	local player = game.Players.LocalPlayer
	local nearbyCustomer = ""

	for _, otherPlayer in ipairs(game.Players:GetPlayers()) do
		if otherPlayer ~= player and otherPlayer.Team.Name == "Customer" then
			local character = otherPlayer.Character
			if character and character:FindFirstChild("HumanoidRootPart") then
				local distance = (character.HumanoidRootPart.Position - player.Character.HumanoidRootPart.Position).magnitude
				if distance <= maxDistance then
					nearbyCustomer = otherPlayer.Name -- Set the nearby customer username
					break
				end
			end
		end
	end

	return nearbyCustomer
end

-- Function to update the order text based on nearby customer
local function updateOrderText()
	-- Update the order text based on the nearby customer's presence
	local nearbyCustomer = checkNearbyCustomer()
	if nearbyCustomer == "" then
		orderTextInfo.Text = "You are holding the Order of ... in your hands. Place the Tray/Plate on a green spot on the tables."
	else
		orderTextInfo.Text = "You are holding the Order of " .. nearbyCustomer .. " in your hands. Place the Tray/Plate on a green spot on the tables."
	end
end

-- Call the updateOrderText function periodically to keep the order text updated
local function updateOrderPeriodically()
	-- Continuously update the order text to reflect nearby customer presence
	spawn(function()
		while true do
			updateOrderText()
			wait(1)
		end
	end)
end

-- Function to check if the order exists in the orders table
local function checkOrderExists(username)
	-- Check if an order exists for a given username
	print("Checking if order exists for username:", username)
	for _, order in pairs(orders) do
		if order.username == username then
			print("Order found for username:", username)
			return true -- Order found
		end
	end
	print("Order not found for username:", username)
	return false -- Order not found
end

-- Function to process the order data
local function processOrder(orderData)
	-- Process the order by sending it to the server and displaying loading animation
	local totalPrice = calculateTotalPrice()

	if totalPrice > 0 then
		resetOrder()
		ReplicatedStorage.remoteEvents:WaitForChild("close_OrderGUI"):FireServer()
		toggleLoadingOrderSent(true)
		wait(3)
		toggleLoadingOrderSent(false)
		wait(0.2)

		local playerTeamName = Players.LocalPlayer.Team and Players.LocalPlayer.Team.Name
		if playerTeamName == "Customer" then
			local clonedTemplateEvent = game:GetService("ReplicatedStorage").orderTemplate:WaitForChild("clonedTemplateEvent")
			-- Pass order data as parameters to clonedTemplateEvent:FireServer()
			clonedTemplateEvent:FireServer(orderData.username, orderData.item1, orderData.item2, orderData.totalprice, orderData.formattedText)
		else
			print("You are not in the Customer Team.")
		end
		resetButtonColor() -- Reset button color
	else
		warn("There are no items in the order or a template already exists.")
	end
end

-- Connect click event for yes request order button
buttonYesRequestOrder.MouseButton1Click:Connect(function()
	-- Process the order when the "Yes" button is clicked
	local orderData = saveOrderData()
	if orderData then
		print("Order data saved:", orderData)
		processOrder(orderData)
	else
		warn("Failed to save order data.")
	end
end)

-- Start updating the order text periodically
updateOrderPeriodically()

I’m sorry but I can’t look through so much code now. I’ll just tell you an easy way of sharing simple data server to client.

You can use ValueBases (NumberValue, StringValue, etc). And put them somewhere that the client can see like ReplicatedStorage, or if they are individualized values per player just parent them to the player instance.

When you change the value from the server it will automatically replicate to the client. You can track when a value changes with ValueBase.Changed.

1 Like

Thank you very much for the information, I’ll put it to the test right now :smiley:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.