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

542 Views Asked by At

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

1

There are 1 best solutions below

2
Milo Chen On BEST ANSWER

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",                                                            
            )
        ),
    )
)