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

194 views Asked by At

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?

2

There are 2 answers

0
Wolfgang Fahl On BEST ANSWER

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

0
bobah On

One can use 'valueFormatter': 'x.part1 + " - " + x.part2' in the columnDefs section, so the updated spec would be:

spec = {
  'columnDefs': [
    {'headerName': 'id', 'field': 'id' },
    {
      'headerName': 'data',
      'field': 'data',
      'valueFormatter': 'x.part1 + " - " + x.part2'
    }
  ],
  'rowData': [
    Row(RowId('a', 'b'), 'c')
  ]
}