Module Script Function is returning nil instead of a table for a client script

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    What I would like to achieve is having my client script (from a PlayerGUI frame) send a returned table that has been processed by a module script function to a server script, all through a remote function.

  2. What is the issue? Include screenshots/videos if possible!
    The issue here is that the module script function is correctly processing the values from the instances in the PlayerGUI, however, the module script is returning nil instead of a table from the function.

This table that I need to be correctly sent through the remote function to the server script, but the server script tells me that the “table” returned in the parameter of the remote function is nil.

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I have tried to look for solutions on Developer Hub, but the case is either posts don’t give the solution, or are not especially relevant to my problem.

To be honest, I have no idea how to solve this, because I have other module scripts in my project that have functions that return tables, and there is no problem.

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so it’s easier for people to help you!

ModuleScript

local assetFilterContent = {}

function assetFilterContent.GetFilter(filterOptions, filterTypes)
	
	local filterOptionTab = filterOptions:GetChildren()

	local categoryParam = filterTypes.Category.FilterTypeInt.Value
	local sortAggregationParam = filterTypes.SortAggregation.FilterTypeInt.Value
	local sortTypeParam = filterTypes.SortType.FilterTypeInt.Value
	local subcategoryParam = filterTypes.Subcategory.FilterTypeInt.Value

	local creatorTypeParam = filterTypes.Creator.FilterTypeInt.Value
	local marketplaceParam = filterTypes.Marketplace.FilterTypeInt.Value
	
	local creatorNameParam = ""
	local MinPriceParam = ""
	local MaxPriceParam = ""

	for i, v in pairs(filterOptionTab) do
		if v:IsA("ImageLabel") then

			if v:WaitForChild("FilterTypeStr").Value == "CreatorName" then
				creatorNameParam = v.TextQuery.ContentText
				
			elseif v.FilterTypeStr.Value == "MinPrice" then
				MinPriceParam = v.TextQuery.ContentText
				
			elseif v.FilterTypeStr.Value == "MaxPrice" then
				MaxPriceParam = v.TextQuery.ContentText
			end
		end
	end
	
								--1					2					3				4				5					6				7			8	
	local filterContentTab = {categoryParam, sortAggregationParam, sortTypeParam, subcategoryParam, creatorTypeParam, creatorNameParam, MinPriceParam, MaxPriceParam}
	
	warn(filterContentTab)
	
	return filterContentTab
end

return assetFilterContent

Client Script

local searchBar = script.Parent
local searchBarFrame = searchBar.Parent
local searchButton = searchBarFrame.SearchButton
local getFilterContent = game.ReplicatedStorage.Asset.Services.GetFilterContent

local assetFilterContentModuleScript = game.ReplicatedStorage:WaitForChild("Asset").Scripts.AssetFilterContent
local assetFilterContentModule = require(assetFilterContentModuleScript)

local catalogFrame = searchBarFrame.Parent
local filterFrame = catalogFrame.FilterFrame



function ReturnSearchBarContent()
	local filterOptions = filterFrame.FilterOptions
	local filterButtons = filterFrame.FilterButtons
	local filterTypes = filterButtons.FilterTypes
	
	local searchBarContent = searchBar.ContentText
	
	getFilterContent:InvokeServer(searchBarContent, assetFilterContentModule.GetFilter(filterOptions, filterTypes))
end

searchButton.MouseButton1Click:Connect(function ()
	ReturnSearchBarContent()
end)

Server Script

getFilterContent.OnServerInvoke = function(player, searchBarContent, catalogParams)
	local playerAssetList = player.PlayerGui.Marketplace.MarketplaceFrame.CatalogFrame.AssetList
	
	--local filteredCatalogApi = FilterCatalogApi(catalogParams)
	
	print(catalogParams)
	
	ClearAssetList(playerAssetList)
	--GetMarketplaceAssets(searchBarContent, playerAssetList, filteredCatalogApi)
end

Additional Information:

When I put a warn function in the Module Script Function to display the table in the output, it does display, but for some reason still, it still returns nil. I still do not know what is causing this. All help is appreciated! Thank you!

1 Like

I tested your scripts, and weird… works for me…
I made my “version” of the GUI following the structure you used in the local script. With a difference that I have nothing inside FilterOptions.

And when sending the table back I create a shallow copy of the table by table.clone()… But I tested it without table.clone and I still get the table normally on server side. I did set all IntValues to 5 to not waste time:
Captura

1 Like

Okay! So I was able to fix my issue by myself. I think I pinpointed what I got wrong. Here is my update.

  1. So for my client script. I did not include this in the information, but I had two client scripts that were tied to the connection of the button GUI (one for a search button, and one for an apply filter button). I “merged” these scripts together so I have cleaner code.

  2. For the parameters being sent to the module script through the client (local) script, I made the filterOptions parameter into a table of all of the instances inside of the filterOptions instance by adding a GetChildren() to the filterOptions. I then edited the module script so that the parameter being received for filterOptions is actually a table, thus shortening and cleaning the code.

  3. For the server script, no edits were made, but the problem had shown that it had been apparently fixed, as in the output, it did not return nil, but it did return the exact table being processed in the module script in relevance to the filterOptions.

Here is the code:

Client Script

local applyFilterButton = script.Parent
local getFilterContent = game.ReplicatedStorage.Asset.Services.GetFilterContent

local filterButtons = applyFilterButton.Parent
local filterFrame = filterButtons.Parent
local filterCatalogFrame = filterFrame.Parent

local searchBarFrame = filterCatalogFrame.SearchBarFrame
local searchBar = searchBarFrame.SearchBar
local searchButton = searchBarFrame.SearchButton

local assetFilterContentModuleScript = game.ReplicatedStorage:WaitForChild("Asset").Scripts.AssetFilterContent
local assetFilterContentModule = require(assetFilterContentModuleScript)

function ApplyFilterContent()
	local searchBarContent = searchBar.ContentText
	local filterTypes = filterButtons.FilterTypes
	local filterOptions = filterFrame.FilterOptions:GetChildren() --***filterOptions is now a table carrying all of the instances in the FilterOptions Instance***
	
	local marketplaceParams = assetFilterContentModule.GetFilter(filterOptions, filterTypes)
	
	print(marketplaceParams)
	getFilterContent:InvokeServer(searchBarContent, marketplaceParams)
end

applyFilterButton.MouseButton1Click:Connect(ApplyFilterContent)
searchButton.MouseButton1Click:Connect(ApplyFilterContent) --***It can be seen here that I added another MouseButton1Click for another button GUI. Like in this post, I merged the two client scripts together to make it cleaner***

Module Script:

local assetFilterContent = {}

function assetFilterContent.GetFilter(filterOptions, filterTypes)

-- ***I removed the local filterOptionTab, which can be seen from my original post***

	local categoryParam = filterTypes.Category.FilterTypeInt.Value
	local sortAggregationParam = filterTypes.SortAggregation.FilterTypeInt.Value
	local sortTypeParam = filterTypes.SortType.FilterTypeInt.Value
	local subcategoryParam = filterTypes.Subcategory.FilterTypeInt.Value

	local creatorTypeParam = filterTypes.Creator.FilterTypeInt.Value
	local marketplaceParam = filterTypes.Marketplace.FilterTypeInt.Value
	
	local creatorNameParam = ""
	local MinPriceParam = ""
	local MaxPriceParam = ""

	for i, v in pairs(filterOptions) do -- ***There is no more filterOptionTab, so I made it filterOptions***
		if v:IsA("ImageLabel") then

			if v:WaitForChild("FilterTypeStr").Value == "CreatorName" then
				creatorNameParam = v.TextQuery.ContentText
				
			elseif v.FilterTypeStr.Value == "MinPrice" then
				MinPriceParam = v.TextQuery.ContentText
				
			elseif v.FilterTypeStr.Value == "MaxPrice" then
				MaxPriceParam = v.TextQuery.ContentText
			end
		end
	end
	
								--1					2					3				4				5					6				7			8	
	local filterContentTab = {categoryParam, sortAggregationParam, sortTypeParam, subcategoryParam, creatorTypeParam, creatorNameParam, MinPriceParam, MaxPriceParam}
	
	warn(filterContentTab)
	
	return filterContentTab
end

return assetFilterContent

Server Script:

getFilterContent.OnServerInvoke = function(player, searchBarContent, catalogParams)
	local playerAssetList = player.PlayerGui.Marketplace.MarketplaceFrame.CatalogFrame.AssetList
	
	--local filteredCatalogApi = FilterCatalogApi(catalogParams)
	
	warn(catalogParams)
	
	ClearAssetList(playerAssetList)
	--GetMarketplaceAssets(searchBarContent, playerAssetList, filteredCatalogApi)
end --***No edits are made here on the server script, but it now prints the table, showing that the table has been successfully sent from the client script to the server script***

Additional Information/Images:

The two buttons arrowed in red are the buttons that connect the MouseButton1Click function to get the FilterOption Instance’s children and send it to the module script for processing and receiving the returned table to send to the server script through a remote function.

The ImageLabels that are circled in blue are what I have been having a problem with, they are what I wanted to get their TextQuery ContentText from to be successfully sent to the server script in a table

Again, here is their location in the Player.PlayerGUI
Screenshot 2023-11-04  C

Finally, here is the successful output. “M” for Module, “C” for client/local, and “S” for Server. And thus, everything has been fixed!

I think I will mark this as the solution, as I believe this was an issue on my part. I think the Instance children table must be sent from the client script to the module script instead of just the instance itself because the module script is unable to just pull the children from the instance to put into a table from just the instance alone.

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