Creating Custom Badges in ag-Grid: A Fun and Engaging Dive into the BadgeCellRenderer

Creating Custom Badges in ag-Grid: A Fun and Engaging Dive into the BadgeCellRenderer

Introduction

Data is the lifeblood of many applications, but it can often feel like trying to find a needle in a haystack when you're presented with an immense volume of numbers. Wouldn't it be great if we could make these figures more digestible and engaging? That's where visual elements like custom badges come into play. Integrating these into your ag-Grid tables not only highlights key information but also adds a dash of color and fun to your data representation.

Today, we'll take an exciting journey into creating a BadgeCellRenderer - a custom cell renderer that lets you design and display custom badges with the icons, colors, and classes of your choice. So, fasten your seatbelts and let's inject some flair into your ag-Grid tables!

A Picture Worth a Thousand Words: Real-World Application

To help you visualize, imagine you're developing an application for a booming shipping company that manages a vast fleet of trucks. The fleet manager wants to view an extensive table of all the trucks, their current statuses, and their assigned drivers. But with hundreds of trucks in the fleet, identifying specific details, such as trucks under maintenance or those out for delivery, becomes akin to finding a needle in a haystack.

Enter our BadgeCellRenderer. By adding vibrant, colorful badges with distinct icons to your ag-Grid table, you can visually differentiate various truck statuses at a glance. For instance, a red badge with a wrench icon can signify a truck under maintenance, while a green badge with a checkmark can indicate a truck out for delivery. This visual differentiation enables the fleet manager to quickly scan the table and immediately understand the status of each vehicle without painstakingly sifting through rows of text.

With this practical scenario in mind, let's roll up our sleeves and dive into the code to bring this BadgeCellRenderer to life.

This post assumes you have a familiarity with the basics of creating a Cell Renderer

No alt text provided for this image
Simplified example of BadgeCellRenderer


Complete Code

import { ICellRenderer, ICellRendererParams } from "ag-grid-community";

interface BadgeParams {
  text: string;
  icon: string;
  color: string;
  customClass: string;
}

export class BadgeCellRenderer implements ICellRenderer {
  private eGui: HTMLElement;
  private params: ICellRendererParams;

  init(params: ICellRendererParams): void {
    this.params = params;
    this.refresh(params);
  }

  createIconElement(iconName: string): HTMLElement {
    const icon = document.createElement("i");
    const iconClasses = iconName.split(" ");
    icon.classList.add(...iconClasses);
    return icon;
  }

  createTextElement(text: string): Text {
    return document.createTextNode(text);
  }

  createBadgeElement({
    text = "Default Text",
    icon = "",
    color = "badge-primary",
    customClass = ""
  }: Partial<BadgeParams>): HTMLElement {
    const badge = document.createElement("span");
    badge.classList.add("badge", color);
    if (customClass) {
      badge.classList.add(customClass);
    }

    badge.appendChild(this.createIconElement(icon));

    const textNode = this.createTextElement(text);
    badge.appendChild(textNode);

    return badge;
  }

  getGui(): HTMLElement {
    return this.eGui;
  }

  refresh(params: ICellRendererParams): boolean {
    if (!params || !params.value) {
      throw new Error("Invalid parameters");
    }

    const { text, icon, color, customClass } = params.value;
    this.eGui = this.createBadgeElement({ text, icon, color, customClass });
    return true;
  }
}



const rowData = 
  {
    truck: "Truck 1",
    driver: "John Doe",
    status: {
      text: "Maintenance",
      icon: "fa-solid fa-wrench",
      color: "badge-danger"
    }
  },
  {
    truck: "Truck 2",
    driver: "Jane Smith",
    status: {
      text: "Delivery",
      icon: "fa-solid fa-truck",
      color: "badge-success"
    }
  },
  {
    truck: "Truck 3",
    driver: "Bob Johnson",
    status: {
      text: "Idle",
      icon: "fa-solid fa-clock",
      color: "badge-warning"
    }
  }
];


const columnDefs = [
  { field: "truck" },
  { field: "driver" },
  {
    field: "status",
    cellRenderer: "badgeCellRenderer"
  }
];[

Diving into the Code

First, let's import the necessary modules and create an interface to define our badge parameters:

import { ICellRenderer, ICellRendererParams } from "ag-grid-community";

interface BadgeParams {
  text: string;
  icon: string;
  color: string;
  customClass: string;
}

Now, let's create the BadgeCellRenderer class, which implements the ICellRenderer interface:

export class BadgeCellRenderer implements ICellRenderer {
  private eGui: HTMLElement;
  private params: ICellRendererParams;

The Init Function

The init function is activated when the cell renderer springs into life. We'll utilize it to establish our parameters and refresh the cell content:

  init(params: ICellRendererParams): void {
    this.params = params;
    this.refresh(params);
  }

Creating Icon and Text Elements

To keep our code clean and manageable, we'll carve out two separate functions, createIconElement and createTextElement:

  createIconElement(iconName: string): HTMLElement {
    const icon = document.createElement("i");
    const iconClasses = iconName.split(" ");
    icon.classList.add(...iconClasses);
    return icon;
  }

  createTextElement(text: string): Text {
    return document.createTextNode(text);
  }

Crafting the Badge Element

The createBadgeElement function forms the nucleus of our renderer. It takes an object with optional properties for text, icon, color, and custom class:

  createBadgeElement({
    text = "Default Text",
    icon = "",
    color = "badge-danger",
    customClass = ""
  }: Partial<BadgeParams>): HTMLElement {
    const badge = document.createElement("span");
    badge.classList.add("badge", color);
    if (customClass) {
      badge.classList.add(customClass);
    }

    badge.appendChild(this.createIconElement(icon));

    const textNode = this.createTextElement(text);
    badge.appendChild(textNode);

    return badge;
  }

Getting the GUI

The getGui function retrieves the HTML element that represents the badge:

  getGui(): HTMLElement {
    return this.eGui;
  }

Refreshing the Cell

The refresh function updates the badge based on the new parameters, ensuring that our cell always displays the correct content:

  refresh(params: ICellRendererParams): boolean {
    if (!params || !params.value) {
      throw new Error("Invalid parameters");
    }

    const { text, icon, color, customClass } = params.value;
    this.eGui = this.createBadgeElement({ text, icon, color, customClass });
    return true;
  }
}

Wrapping Up

And there we have it! Our very own custom BadgeCellRenderer class, capable of sprucing up our ag-Grid cells with colorful badges. This class is flexible and reusable, allowing you to create badges with customizable text, icons, colors, and additional classes.

Final Thoughts

Remember that good code is like a good joke: It's all about delivery! The BadgeCellRenderer is a fun way to deliver your data and add a pop of color to your application.

While our BadgeCellRenderer class is relatively simple, it demonstrates some essential concepts in TypeScript and DOM manipulation. It also showcases the power of ag-Grid's custom cell renderers, opening the door to countless other customizations.

Now that you have this BadgeCellRenderer in your toolkit, you can experiment with it and tweak it to fit your specific needs. Maybe you want to add tooltips to your badges, or perhaps you want to make the badges clickable and open a modal when clicked. The sky's the limit!

Don't be afraid to get creative and make your data grid not just informative, but also fun and engaging for your users. After all, who said data presentation had to be boring?

That's it for today's post. We hope you found it helpful and, most importantly, fun! Happy coding!

Written with the assistance on AI.

To view or add a comment, sign in

Insights from the community

Others also viewed

Explore topics