How would i use metatables to tell when a value in a table has changed?

I’m pretty new to using metatables, so how would i tell when a value has been changed in table?

--example
local mytable = {x = 5, y = 3}

mytable.x = 4 --how do i make this trigger some sort of event

from what i understand, __index and __newindex only fire when either the value or index is nil, so how would i make something fire when the value or index isn’t nil?
Would i even need metatables to do this?

2 Likes
local myTable = { -- the target table
    x = 5,
    y = 3
}

local meta = { -- the meta table to attach the table to
    __newindex = function(...) -- whenever a value is added, this function will fire
        print(...) -- you can put anything here, but this will print the values of the varargs
        -- __newindex = function(table, index, newValue) <-- this is what the function arguments look like
    end
}

setmetatable(myTable, meta) -- attach the tables
myTable.z = 10 -- add a "z" value 

-- i haven't tested this so i don't know if it works
1 Like

I tried the code but for some reason the __newindex doesn’t fire, as the only thing in the output is the line 17 code

Yea, I made some minor errors and edits. __newindex only fires when a new value is added to the table

myTable.x = nil
myTable.x = 10

ah right, is there no way to check when a value is edited then

You can, but you’d have to mess around with metamethods such as __index

Your best bet would be to create a proxy table (or an userdata with newproxy(true) if you want a perfect one) and check if newly assigned value is different than the old one using __newindex metamethod:

local mytable = {x = 5, y = 3}
local Metatable = {
    __index = mytable,
    __newindex = function(Table, Key, Value)
        if mytable[Key] ~= Value then
            --This part of the code will run if new value is different than the old one.
        else
            --This part of the code will run if the new value is the same with the old one.
        end
    end
}
local MyTable = setmetatable({},Metatable)
MyTable.x = 10
7 Likes

Thanks this seems to work :grinning: