pythonbuttonlowcodepython-reflex

How to create a table with buttons element in a column with Pynecone?


The table's last column (action) contains pc.button, that can get data in the row that the button residing in, and then send that data to a State variable.
Some thing like this:

name age job action
John 20 Developer Update
May 23 Designer Update

I have tried pc.list like this:

return pc.center(
   pc.list([
     ["name","age","job","action"],
     ["John",20, "Developer", pc.button("Update", on_click=State.update_employee)],
     ["May",23, "Designer", pc.button("Update", on_click=State.update_employee)],
   ])
)

but pc.list can only take in python primitive types (str,int,float...). Is there any way to add multiple components progamatically to another Pynecone component


Solution

  • https://youtube.com/shorts/u-TUSQ9DkCw <-- Example here I write the following full example for what you want.

    The simple answer is to use table_container. But we need to care about some detail.

    from pcconfig import config
    import pynecone as pc
    class Member(pc.Model, table=True):
        ename:str # The attribute cannot be call "name", so we use ename here
        age:int
        job:str
        def __init__(self, ename,age,job):
            self.ename=ename
            self.age =age
            self.job =job
        def __repr__(self) -> str:
            return "("+self.ename+","+self.age+","+self.job+")"
    
    class State(pc.State):    
        members:list[Member] = [
            Member("John",20,"Developer"),
            Member("May",23,"Design"),
            Member("Milo",18,"Teacher"),
            Member("Aloha",48,"CEO"),
        ]    
    
        def delete_member(self,member_name:str):
            del_idx:int = -1
            for i in range(len(self.members)):
                if(self.members[i].ename == member_name):
                    del_idx = i
                    break
            if(del_idx > -1):
                del self.members[del_idx]
            return
    
    def index() -> pc.Component:
        return pc.center(
            pc.vstack(
                pc.vstack(
                    pc.hstack(
                        pc.heading("Members"),
                    ),
                    pc.table_container(
                        pc.table(
                            pc.thead(
                                pc.tr(
                                    pc.th("Name"),
                                    pc.th("Age"),
                                    pc.th("Job"),
                                    pc.th("Action"),
                                )
                            ),
                            pc.tbody(
                                pc.foreach( State.members, lambda member: 
                                    pc.tr(
                                        pc.td(member.ename),
                                        pc.td(member.age),
                                        pc.td(member.job),
                                        pc.td(
                                            pc.button(
                                                "Delete",
                                                on_click=lambda: State.delete_member(member.ename),
                                                bg="red",
                                                color="white",                                                            
                                            )
                                        ),
                                    )
                                )
                            ),
                        ),
                        bg="#F7FAFC ",
                        border="1px solid #ddd",
                        border_radius="25px",
                    ),
                    align_items="left",
                    padding_top="7em",
                ),
            ),
            padding="1em",
        )
    
    
    # Add state and page to the app.
    app = pc.App(state=State)
    app.add_page(index, title="table container")
    app.compile()
    

    (1) You need to define a class. In my case, it is Member(pc.Model, table=True).
    You must add (pc.Model, table=True)
    Can we use [list[list[str]] to represent the self.members?
    The answer is NO.
    That's we we use members:list[Member] in State but not members:list[list[str]].

    (2) When your code satisfies the above condition 1, then we can
    use pc.foreach() to generate table's data in UI.

    pc.foreach( State.members, lambda member: 
        pc.tr(
            pc.td(member.ename),
            pc.td(member.age),
            pc.td(member.job),
            pc.td(
                pc.button(
                    "Delete",
                    on_click=lambda: State.delete_member(member.ename),
                    bg="red",
                    color="white",                                                            
                )
            ),
        )
    )