Detecting if a key's value is changed in a table

  1. What do you want to achieve? I want to detect if a key’s value in a table has been changed.

  2. What is the issue? There’s no issue really, I’m just looking for another way to detect a key’s value change in a table.

  3. What solutions have you tried so far? I tried making a proxy table that reflects change on the real table. Something like this:

local t = {
    A = 10
}

local proxy = setmetatable({{}, {
    __index = function(self, k)
        return t[k]
    end,
    __newindex = function(self, k, v)
        t[k] = v
        --A signal that fires
    end
})

If there is another way to do this, please feel free to reply to this topic as I really need it for my module.

You could possibly use “A” to be equaled to a instance either a number or int value then use that instace changed function within the table I just thought of it

Why not just write a function that you can call to change your values and then fire an event? I guess it depends on your use case but it doesn’t seem necessary to have a metatable.

local function addPoints(player, pointsToAdd)
    player.Points += pointsToAdd
    addedPoints:Fire(...)
end

I’ve tried this but it isn’t good in this case as my module is related to ProfileService.

I could but if I have to change a lot of keys I will need to make a lot of int/number values and I don’t need to do t.A.Value += 15 just for that.

If you really want to go forward with this, then the approach you have in the initial post seems decent enough. You can rewrite it in a slightly different way like this:

local proxy = {}
-- signal class implementation
local Signal = require(script.FastSignal)

function proxy.new(state)
	local self = {
		_state = state,
		_propertyChangedSignals = {}
	}

	for property, value in pairs(state) do
		self._propertyChangedSignals[property] = Signal.new()
	end

	return setmetatable(self, proxy)
end

function proxy:GetPropertyChangedSignal(property)
	local signal = self._propertyChangedSignals[property]
	-- maybe throw error if value is nil or protected
	return signal
end

function proxy:__index(property)
	local value = proxy[property] or self._state[property]
	-- maybe throw error if value is nil or protected
	return value
end

function proxy:__newindex(property, value)
	local currentValue = self._state[property]
	-- maybe throw error if value is nil or protected
	if currentValue ~= value then
		self._state[property] = value

		local signal = self._propertyChangedSignals[property]

		if signal then
			signal:Fire()
		end
	end
end

return proxy

(You can find a custom signal class implementation or use a BindableEvent.)

Example usage:

local Proxy = require(script.Proxy)

local test = Proxy.new({
	value1 = 'a',
	value2 = true,
	value3 = 2
})

local cn1 = test:GetPropertyChangedSignal("value1"):Connect(function()
	print("value1 changed:", test.value1)
end)

local cn2 = test:GetPropertyChangedSignal("value2"):Connect(function()
	print("value2 changed:", test.value2)
end)

local cn3 = test:GetPropertyChangedSignal("value3"):Connect(function()
	print("value3 changed:", test.value3)
end)

test.value1 = 'b'
test.value2 = not test.value2
test.value3 += 1

cn3:Disconnect()

test.value3 -= 1
test.value2 = not test.value2
test.value1 = 'a'

test.value1 = test.value1
test.value2 = test.value2

But overall, this is essentially the same approach. I’m not sure if I understood your post correctly or if you were looking for something more different.

1 Like

Thanks for this and it works but is there any other way to do this?