Having issues with string.find

Hi! I’m trying to make a search system, I’m starting out with a basic test with string.find, it doesn’t seem to be working. Can I have any help?
Local Script Parented to TextBox

script.Parent.InputEnded:Connect(function()
	for i,Viewport in pairs(script.Parent.Parent.ScrollingFrame:GetChildren()) do
		if Viewport.ClassName == "ViewportFrame" then
			local HasText = string.find(string.lower(script.Parent.Text), string.lower(Viewport:FindFirstChildOfClass("Model").Name))
			print(Viewport:FindFirstChildOfClass("Model").Name .. "'s current stance on having the string is " .. HasText)
		end
	end
end)
2 Likes

An agrument is missing here, this is the fixed script :

script.Parent.InputEnded:Connect(function()
	for i,Viewport in pairs(script.Parent.Parent.ScrollingFrame:GetChildren()) do
		if Viewport.ClassName == "ViewportFrame" then
			local HasText = string.find(string.lower(script.Parent.Text), string.lower(Viewport:FindFirstChildOfClass("Model").Name), "")
			print(Viewport:FindFirstChildOfClass("Model").Name .. "'s current stance on having the string is " .. HasText)
		end
	end
end)

EDIT : I just fixed it, typed wrong :stuck_out_tongue:

Which argument was missing? So I know what to do in the future and am not blindly copying and pasting code.

Also, it’s saying a number was expected and it got a string.

Wait I’m wrong, thats for string.gsub , my fault, use this code and let me see the output :

script.Parent.InputEnded:Connect(function()
    print("Passed")
	for i,Viewport in pairs(script.Parent.Parent.ScrollingFrame:GetChildren()) do
        print("Passed")
		if Viewport:IsA("ViewportFrame") then -- :IsA function better than check it ClassName. I recommended you to use it instead.
            print("Passed")
			local HasText = string.find(string.lower(script.Parent.Text), string.lower(Viewport:FindFirstChildOfClass("Model").Name))
			print(Viewport:FindFirstChildOfClass("Model").Name .. "'s current stance on having the string is " .. HasText)
		end
	end
end)

How many time the “Passed” were printed in the output?


Three times, I think, but there was an error, too. HasText was nil for some reason. I typed in “as”, trying to search for the model “Astro”, which should work with them both being string.lower'd, I think.

This is the error, did you forgot anything?


Nope.
Here’s a visual chain of it.
script.Parent.Parent.ScrollingFrame:GetChildren() (it also checks if they are a viewport) :FindFirstChildOfClass("Model").Name

I have created a finding name function here, use it:

function FindChildFromLetter(parentOfChild, letter)
    local foundChild = false
    local child = nil
    if parentofChild and tostring(letter) then
        for _, v in pairs(parentOfChild:GetChildren()) do
            if not foundChild and child ~= nil then
               if string.find(v.Name, tostring(letter) then
                  if v:IsA("Model") then
                     foundChild = true
                     child = v
                  end
               end
            end
        end
    end
    return child
end

---------- Example

local text = "a"
local parent = script.Parent

local astro = FindChildFromLetter(parent, text)
print(astro)

EDIT : Create a Local Script and parent this into the viewport frame, it should work and print out “Astro”

Can you explain a bit more how this works?

Firstly, it will check if the parent and the letter you typed and make sure its not a nil, after that, it will get get every children inside it parent and check if the code has found the child yet, if not, it will use string.find to see if the children name has the same letter with the text you typed, if true, check if its a model, if yes then it will make the child value to the children has just checked. Then at the end, it will return the child found which is Astro.

EDIT : The parent here should be the viewportFrame and the letter should be the text player typed in the search bar.

1 Like
           if string.find(v.Name, tostring(letter) then -- add a parenthesis after the tostring letter  this will error if you don't

Ah yes, I forgot, Im not scripting in studio, sorry!

I’m trying this and all I’m getting is nil.

local LibraryModule = require(game.ReplicatedStorage.LibraryModule)

script.Parent.InputEnded:Connect(function()
	local HasText = LibraryModule:FindChildFromLetter(script.Parent.Parent.ScrollingFrame, script.Parent.Text)
	print(HasText)
end)

This is it in the module but it shouldn’t be that important since I just edited you forgetting to add a ) to close something.

-- Find Child From Letter
function module:FindChildFromLetter(parentOfChild, letter)
	local foundChild = false
	local child = nil
	if parentOfChild and tostring(letter) then
		for _, v in pairs(parentOfChild:GetChildren()) do
			if not foundChild and child ~= nil then
				if string.find(v.Name, tostring(letter)) then
					if v:IsA("Model") then
						foundChild = true
						child = v
					end
				end
			end
		end
	end
	return child
end

parentOfChild should be the ViewportFrame, not the ScrollingFrame!

This should be the fixed one, sorry!

function module:FindChildFromLetter(parentOfChild, letter)
	local foundChild = false
	local child = nil
	if parentOfChild and tostring(letter) then
		for _, v in pairs(parentOfChild:GetChildren()) do
			if not foundChild and child ~= nil then
				if string.find(tostring(letter), v.Name) then
					if v:IsA("Model") then
						foundChild = true
						child = v
					end
				end
			end
		end
	end
	return child
end

The point is I get the children of the scrolling frame, and search for the model inside the scrolling frame’s viewports, to see which are it. I’m not searching through a single viewport.

function module:FindChildFromLetter(parentOfChild, letter)
	local foundChild = false
	local child = nil
	if parentOfChild and tostring(letter) then
		for _, v in pairs(parentOfChild:GetChildren()) do
			if not foundChild and child ~= nil and v:IsA("ViewportFrame") then
				for _, v1 in pairs(v:GetChildren())
                                   if string.find(tostring(letter), v1.Name) then
					if v1:IsA("Model") then
						foundChild = true
						child = v1
					end
				end
                                end
			end
		end
	end
	return child
end

Like you said, I fixed the code a bit so it can search into the viewportFrame, you can use the function to search now.

From my understanding of what you’re attempting here, it seems like you for the most part just have your logic backwards with string.find.

What you’re essentially doing here is:

string.find(TextBox.Text, "Model") -- with "Model" being interchangeable with whatever the model's name is

The problem is that you’re searching the textbox for the model’s name rather than searching for a model with the textbox text. You want to swap this logic around if that’s what you’re trying to achieve.

script.Parent.FocusLost:Connect(function()
	for i,Viewport in pairs(script.Parent.Parent.ScrollingFrame:GetChildren()) do
		if Viewport.ClassName == "ViewportFrame" then
			local HasText = script.Parent.Text~="" and string.find(string.lower(Viewport:FindFirstChildOfClass("Model").Name), string.lower(script.Parent.Text))
			print(Viewport:FindFirstChildOfClass("Model").Name .. "'s current stance on having the string is " ..(HasText or 0))
		end
	end
end)

Edit: The reason why I added the (HasText or 0) line is just in case HasText turns up nil, in which case you can assume that there were 0 matches.

2 Likes