Simple table with list of objects shows no updates

Hi!

i want to see updates in my table, when objects are updated.

How to implement this? How to tell the table to “reload” the elements.

The Text-Field shows the updates.

Looks like reflex somewhere looses the connection/reference between the objects. Is this related to the table of rx.Model?



import reflex as rx

from rxconfig import config

class simplePart(rx.Model, table=True):
    def __init__(self, desc="", price=0):
        self.desc=desc
        self.price=price
        rx.Model.__init__(self)

    desc: str
    price: float


class State(rx.State):
    debug: str="dbg"
    
    parts: list[simplePart] = []
    #sp1=SpendPart("desc1", 500.1)
    
    sp1=simplePart()
    sp1.desc="desc1"
    sp1.price=1.11
    

    sp2=simplePart()
    sp2.desc="desc2"
    sp2.price=2.22
    
    parts.append(sp1)
    parts.append(sp2)

    def updatepart1(self):
        self.sp1.price+=20
        self.debug+="upd"



def parts_row(part: simplePart):
    return rx.table.row(
        rx.table.cell(
            part.id
        ),
        rx.table.cell(
            part.desc
        ),
        rx.table.cell(
            part.price
        ),
    )    

def parts_table():
    return (
        rx.table.root(
            rx.table.body(
                rx.foreach(
                    # State.UpdateSelectedParts(), parts_spend3
                    State.parts, parts_row
                ),
            ),
        ),
    )


def index() -> rx.Component:


    return rx.container(
        rx.text(f"debug: {State.debug}"),
        rx.text(State.sp1.price),
        parts_table(),
        rx.button(
            "UpdatePart1",
            on_click=State.updatepart1,
         )
    )


app = rx.App()
app.add_page(index)

Greets from Bavaria, Freisei

What’s happening here is the sp1 and sp2 values are being added to parts default value.

Because parts default is a mutable type (list), it’s getting deep copied for each new state instance. Similarly, self.sp1 and self.sp2 are also being deep copied from how they are defined at the class level.

I’d probably structure this a bit differently.

import reflex as rx

from rxconfig import config

class simplePart(rx.Model, table=True):
    def __init__(self, desc="", price=0):
        self.desc=desc
        self.price=price
        rx.Model.__init__(self)

    desc: str
    price: float


class State(rx.State):
    debug: str="dbg"
    
    parts: list[simplePart] = []
    #sp1=SpendPart("desc1", 500.1)
    
    sp1=simplePart()
    sp1.desc="desc1"
    sp1.price=1.11
    

    sp2=simplePart()
    sp2.desc="desc2"
    sp2.price=2.22
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # Link these values up on the instance
        self.parts.append(self.sp1)
        self.parts.append(self.sp2)

    def updatepart1(self):
        self.sp1.price+=20
        self.debug+="upd"
        # Reassign parts list to mark it dirty for delta calculation
        self.parts = self.parts


def parts_row(part: simplePart):
    return rx.table.row(
        rx.table.cell(
            part.id
        ),
        rx.table.cell(
            part.desc
        ),
        rx.table.cell(
            part.price
        ),
    )    

def parts_table():
    return (
        rx.table.root(
            rx.table.body(
                rx.foreach(
                    # State.UpdateSelectedParts(), parts_spend3
                    State.parts, parts_row
                ),
            ),
        ),
    )


def index() -> rx.Component:


    return rx.container(
        rx.text(f"debug: {State.debug}"),
        rx.text(State.sp1.price),
        parts_table(),
        rx.button(
            "UpdatePart1",
            on_click=State.updatepart1,
         )
    )


app = rx.App()
app.add_page(index)

Note that because the table is built from State.parts, after updating some constituent value, it’s still necessary to mark parts as dirty via reassignment, self.parts = self.parts.

Thank you very much, masenf! For now i dont understand all of you explenations, but even some :slight_smile:

The most important thing for now: it works!