ag-gridnicegui

Show an object with several fields in a single cell with python nicegui ag-grid


Python side code:

@dataclass(frozen=True)
RowId:
  key_part1: str
  key_part2: str

@dataclass
Row:
  id: RowId
  data: str


spec = {
  'columnDefs': [
    {'headerName': 'id', 'field': 'id' },
    {'headerName': 'data', 'field': 'data'}
  ],
  'rowData': [
    Row(RowId('a', 'b'), 'c')
  ]
}

ui.aggrid(spec)

Results in the following value rendered for the id field in the browser:

[object Object]

Also browser console has a warning suggesting to provide a custom formatter for data type object (how do I do it?).

Can it be improved?


Solution

  • see the product example in https://github.com/zauberzeug/nicegui/discussions/2028

    products list in ag grid

    The key idea is to have an as_html:

    @dataclass
    class Product:
        """
        Data class representing a product.
    
        Attributes:
            title (str): The title of the product.
            image_url (str): The URL of the product image.
            price (str): The price of the product.
            asin (Optional[str]): The Amazon Standard Identification Number (ASIN) of the product, 
                                  which is a unique identifier on Amazon's platform.
        """
        title: str
        image_url: str
        price: str
        asin: Optional[str] = None
        ean: Optional[str] = None
    
        @property
        def amazon_url(self) -> str:
            return f"https://www.amazon.com/dp/{self.asin}" if self.asin else None
    
        def as_html(self, img_size: int = 128) -> str:
            """
            Returns an HTML representation of the product with an image thumbnail and a link to the product page.
    
            Parameters:
                img_size (int): Size of the image thumbnail.
    
            Returns:
                str: HTML string representation of the product.
            """
            html = f'<div>'
            html += f'<img src="{self.image_url}" alt="{self.title}" width="{img_size}" height="{img_size}"/>'
            if self.amazon_url:
                html += f' <a href="{self.amazon_url}">{self.title}</a>'
            else:
                html += f' {self.title}'
            html += f' - {self.price}'
            html += f'</div>'
            return html
    

    and a special list of dicts to load in the ag_grid:

        def get_aggrid_lod(self) -> List[Dict[str, str]]:
            """
            Generates a list of dictionaries for ag-Grid representation of the products.
    
            Returns:
                List[Dict[str, str]]: List of product information formatted for ag-Grid.
            """
            lod = []
            for index, product in enumerate(self.products, start=1):
                product_dict = {
                    "#": str(index),
                    "Product": product.as_html(),
                    "ASIN": Link.create(product.amazon_url, product.asin) if product.asin else "",
                    "Title": product.title,
                    "EAN": product.ean if product.ean else "",
                    "Price": product.price
                }
                lod.append(product_dict)
            return lod
    

    The source code is at https://github.com/WolfgangFahl/scan2wiki/blob/main/scan/product.py and https://github.com/WolfgangFahl/scan2wiki/blob/main/scan/webcam.py

    where you'll find the loading of the ag_grid