How To: Bring Your Own AG Grid

Prev Next

This how-to guide details how to create a custom (Bring Your Own) AG Grid component. This BYO Unqork component uses a third-party library to embed a customizable AG Grid data table in Express View. It also acts as a wrapper, translating Unqork's data format into a format that the AG Grid library can understand and interact with.

To learn more about AG Grid, view the AG Grid website: https://www.ag-grid.com/.

The Bring Your Own feature is intended for developers who have a strong understanding of the Unqork Designer Platform and JavaScript.

BYO AG Grid Component Ideation

For this example, the fictional client company "ABC" wants to implement a third-party library called AG Grid as a data table to use in a custom Unqork component. The component must let Creators create multiple columns that contain a key and label field.  They also want the component to accept a string containing an array of objects with table data. Additionally, the company wants a custom event that emits when a user clicks on an AG Grid’s cell.

As the developer assigned to this task, break down and document the client's ask into actionable sections:

  • Asset Types: What’s needed to meet the client's requirements of an averaging and rounding asset?

    • Component(s): Does the client's request require the creation of something not currently supported in the Unqork platform?

    • Event(s): Does the asset need to emit an event when it's used? What action should emit the event?

    • Operation(s): Does the asset need to be manipulated by other elements using an operation?

  • Inputs & Outputs: Catalog a list of potential inputs and outputs for the asset. Events are typically outputs in this list.

  • Libraries: Does this asset require an external library? Does the library perform the functions requested by the client? Do Creators need to understand how to use the library in Unqork?

  • Naming Scheme: Develop a naming scheme for the asset that aligns with Unqork values and avoids conflicts with potential future custom assets.

    To understand naming scheme limitations, view the Important callout in the overview of our Bring Your Own (BYO): Understanding the manifest.json File article.

Now that the client has described the ask, create a document detailing all the potential elements the operation asset requires.

Example Ideation Documentation

The sections below detail the product requirements that meet the client's request. Developers use this information to implement the component’s JavaScript, create the manifest file and package, and package it to the Unqork Designer Platform.

Component(s)

A custom Unqork component that imports an AG Grid data table.

Component Name

Description

AG Grid

An imported AG Grid with the following configuration settings:

  • Column Definitions (Array of Objects): Contains the Key and Label fields required to map and display table data to the AG Grid.

    • Key (Field): Maps the Value field to the AG Grid column.

    • Label (Field): The header display value for the column.

  • Value (Field): Accepts an Array of table data.

Event(s)

An event used as part of the Events & Operations Builder.

Parameter

Object Type

Description

AG Grid Cell Clicked

agGridCellClicked

An event that is emitted when an end-user clicks on an AG Grid Cell. The event includes a payload with the cell value.

Input(s)

Creators use the input fields to map and label columns.

Parameter

Object Type

Description

columnDefinitions

array

An array of objects that defines the grid's columns. The asset developer maps these values to the AG Grid column function.

The columns definition contains the following keys:

  • key: Maps the table data from the value field to the column.
    Corresponds to the Key field in the component’s configuration drawer.

  • label: Creates a header display value.
    Corresponds to the Label field in the component’s configuration drawer.

Creators use these fields to define map table data to the component and label the column headers.

value

string

A JSON string that represents the data for the grid's rows.

Corresponds to the Value field in the component’s configuration drawer.

Libraries

This component imports the AG Grid library for rendering table data. See examples of importing an AG Grid in their Get Started documentation: https://www.ag-grid.com/javascript-data-grid/getting-started/.

Library Name

Description

Documentation Link

AG Grid

A free, open source library that provides a high-performance, feature-rich, and fully customizable Data Grid.

Asset developers should perform an additional review of this library to verify it meets the client’s needs and what is required of Creators to use it.

https://www.ag-grid.com/

Naming Scheme

Verify that all naming values do not conflict with existing Unqork assets or other custom assets in the environment.

IMPORTANT

Unqork does not enforce programmatic name spacing for custom asset types. All type values for components, operations, and events must be globally unique. If multiple custom assets share the same type, or if a custom asset uses a type that conflicts with a native Unqork type, the runtime will render or execute only the first matching definition. Doing so leads to unpredictable behavior, asset shadowing, or broken functionality—especially when bundling or importing multiple packages.

It is the responsibility of the developer to ensure type uniqueness to prevent collisions. Component, operation, and event types require a unique name to avoid collision issues.

To avoid namespace issues, prefix custom components with a name unique to your company or application. For example, if a company named ABC creates a Card Panel component. The component's name space could be abcCardPanel.

Asset Type

Asset Name

Naming Scheme

Component

Ag Grid

exAvgAndRound

Event / Output

AG Grid Cell Clicked

agGridCellClicked

Input

Column Definition

columnDefinitions

Input

Value

value

Create the manifest.json File

The manfest.json file serves as the contract between Unqork and the AG Grid implementation. In this file, you’ll specify the AG Grid components and event properties.

{
  "name": "AgGrid",
  "version": "1.0.0",
  "main": "agGrid.js",
  "type": "custom",
  "productType": "BYO",
  "description": "AG Grid integration with Unqork",
  "components": [
    {
      "name": "AG Grid",
      "type": "agGrid",
      "description": "AG Grid component for Unqork",
      "model": {
        "type": "object",
        "properties": {
          "columnDefinitions": {
            "name": "Column Definitions",
            "type": "array",
            "description": "Column definitions for this grid (currently only supporting key and label)",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string",
                  "description": "Unique key for the column"
                },
                "label": {
                  "type": "string",
                  "description": "Display label for the column"
                }
              }
            }
          },
          "value": {
            "name": "Grid Data (JSON)",
            "type": "string",
            "description": "JSON string of data for the grid"
          }
        },
        "required": ["columnDefinitions"]
      },
      "events": [
        {
          "name": "AG Grid Cell Clicked",
          "type": "agGridCellClicked",
          "description": "This event is triggered when the user clicks on a grid cell.",
          "stability": "STABLE"
        }
      ]
    }
  ]
}

The following fields are used at the root level of the manifest:

Field

Type

Required

Description

name

string

Checkmark

A unique identifier for the package. For example, MyCompanyNameAssets.

version

string

Checkmark

The semantic version number. For example, 1.0.0.

main

string

Checkmark

The relative path to the JavaScript entry file. For example, agGrid.js.

type

enum

Checkmark

The package type. Currently, the only supported value is custom.

productType

enum

Checkmark

The target platform feature. Currently, the only supported value is BYO.

description

string

Checkmark

A description that displays in the Admin Panel after installation.

components

array<component-description>

Optional

A list of component definitions included in the package.

events

array<event-description>

Optional

List of event definitions.

Understanding the components[0] definition.

This is the main definition for the AG Grid component itself. This definition includes the name, inputs, and events for the asset.

Property

Description

name and type

Define the component's name and its internal identifier. The type (agGrid) must match the export name in the JavaScript file (agGrid.js) so Unqork can link the JSON definition to the correct code.

model

This object defines a custom event. It exports a model that describes the structure of the event's payload (name and type). Doing so lets other parts of the Unqork platform use and understand the event that the component emits.

columnDefinitions

This is a required property that defines the columns of the grid. The schema specifies that it must be an array of objects, where each object has a key (for internal use) and a label (for display).

value

This property is where the grid's data is provided. The schema expects a JSON string to define the rows of the grid.

events

This section defines the custom events the component can emit.

name and type

These define the agGridCellClicked event's name and its unique identifier.

description

Explains when the event is triggered.

stability

The STABLE tag indicates that this event's API is reliable and will not change without warning.

Implement the AG Grid Component

For this example, create a file called agGrid.js. In this file, create a component that does the following:

  1. Imports the AG Grid Library.

    NOTE

    Unqork does not support the JavaScript Import syntax at this time. Instead, developers must copy and paste the AG Grid code into the file.

  2. Creates a Shadow DOM as part of the BYO implementation requirements.

  3. Initializes the Unqork Runtime API as a part of the BYO implementation requirements.

  4. Subscribes to column definitions, updating the Express View rendering to match.

  5. The component subscribes to state changes for the grid's value property, automatically updating the component to reflect any changes configured in the Module Builder.

  6. Emits an event (onAgGridCellClicked) back to the Unqork runtime. Creators can configure the event using the Operations Builder to trigger downstream logic.

  7. Validates input data and parses it as JSON. Reducing inconsistencies with Unqork’s platform.

  8. Map’s Unqork’s input format to AG Grid’s input format.

  9. Exports and renders the AG Grid data into the Unqork Designer platform.

Review the code example below for more information on each method:

The comments in the JavaScript below are written in the JSDoc format. For more information on JSDoc block tags (@param, @return), visit the JSDoc website: https://jsdoc.app/.

// AgGrid Import //
// See import examples in AG Grid's Get Started Documentation: https://www.ag-grid.com/javascript-data-grid/getting-started/

class UnqorkAgGridComponent extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({ mode: 'open' })

    this.gridOptions = {
      columnDefs: [],
      rowData: [],
      
    }
  }

  /**
   * This is the only required method to integrate with the Unqork system
   * 
   * @param {*} api The interface to the Unqork Runtime, used for both
   *                monitoring state and emitting events
   */
  initialize(api) {
    this.config = api.state.currentState()
    this.api = api

    if (this.config.columnDefinitions?.length) {
      const defs = this._normalizeInput(this.config.columnDefinitions)
      this.gridOptions.columnDefs = this._formatColumnDefinitions(defs)
    }

    if (this.config.value?.length) {
      this.gridOptions.rowData = this._normalizeInput(this.config.value)
    }

    this.renderGrid(this.shadowRoot, this.gridOptions)
    this.subscribeColumnDefs()
    this.subscribeData()
  }

  /**
   * Subscribe to the source for column definitions
   * 
   * This can be made more robust by first using
   * api.state.state$('columnDefsReference') to subscribe to
   * any changes to that value (i.e. the target key), and then using
   * resolveByKey$ to resolve the current value of that key.
   */
  subscribeColumnDefs() {
    this
      .api
      .state
      .state$('columnDefinitions').subscribe((columnDefs) => {
        console.log('AG Grid column definitions updated to', columnDefs)
        // This _should_ be an array, but sometimes components try to set it as a
        // JSON string instead, so we handle that here
        const value = typeof(columnDefs) === 'string' ? JSON.parse(columnDefs) : columnDefs
        this.gridOptions = {
          rowData: this.gridOptions.rowData,
          columnDefs: value ? this._formatColumnDefinitions(value) : [],
        }
        this.updateGrid(this.gridOptions)
      })
  }

  subscribeData() {
    this.api.state.state$('value').subscribe((rowData) => {
      console.log('AG Grid value updated to', rowData)
      // We support setting this as a JSON string or already parsed array of objects
      // so handle that here
      const value = typeof(rowData) === 'string' ? JSON.parse(rowData) : rowData
      this.gridOptions = {
        rowData: value || [],
        columnDefs: this.gridOptions.columnDefs,
      }
      this.updateGrid(this.gridOptions)
    })
  }

  updateGrid(gridOptions) {
    console.log('Updating AG Grid', gridOptions)
    this.gridApi.updateGridOptions(gridOptions)
  }

  async renderGrid(document, gridOptions) {
    console.log('Rendering AG Grid component', {gridOptions, agGrid, windowAgGrid: window.agGrid})

    document.innerHTML = this.view()
    this.gridEl = document.querySelector('#myGrid')
    this.gridApi = window.agGrid.createGrid(this.gridEl, gridOptions)

    // Set this here so that it doesn't overridden when we update gridOptions
    this.gridApi.addEventListener('cellClicked', (ev) => {
      console.log('Emitting AG Grid Cell Clicked Event', ev)
      this.emitCellClickedEvent(ev)
    })

    console.log('Created AG Grid', {
      document,
      gridOptions,
      gridEl: this.gridEl,
      gridApi: this.gridApi,
    })
  }

  // Emit an event when a cell is clicked
  // Full docs: https://www.ag-grid.com/javascript-data-grid/grid-events/#reference-selection-cellClicked
  emitCellClickedEvent = (ev) => {
    this.api.events.emit({
      name: 'onAgGridCellClicked',
      payload: ev
    })
  }

  view() {
    return `
      <div id="myGrid" style="height:500px"></div>
    `
  }

  /**
   * Input data can be either JSON string or actual data, due to
   * Unqork data constraints, so ensure it's proper data before
   * using
   */
  _normalizeInput(val) {
    return typeof(val) === 'string' ? JSON.parse(val) : val
  }

  /**
   * We store column definitions with standard key/label properties
   * But AG Grid using different property names, so we map it here
   */
  _formatColumnDefinitions(defs) {
    return defs.map(({key, label}) => {
      return {
        field: key,
        headerName: label ?? key
      }
    })
  }
}

// This definition defines the state settings (model) for this component
// It mirrors the fuller description in manifest.json and will
// eventually be used to auto-generate the manifest.json JSON schema
class AgGridDefinition {
  columnDefsReference
  dataReference
}

// Actual export that exposes both the view layer and the model
// and is consumed by the Unqork Runtime for both configuration and
// execution
// All of these are `async` to allow for us to load them on demand
// without impacting initial page load performance
export const agGrid = {
  model: async () => AgGridDefinition,
  view: async () => UnqorkAgGridComponent,
}

// This definition describes the schema of the event that is emitted
// when the user clicks on an item
class CellClicked {
  name = 'agGridCellClicked'
  payload = {
    index,
    text,
  }
}

// This export is used to expose the event to the Unqork Runtime
export const agGridCellClicked = {
  model: async () => CellClicked,
}    

Understanding UnqorkAGGridComponent  Class

This is a web component that encapsulates all the AG Grid functionality.

Method

Description

constructor()

Sets up the component's internal state, including the Shadow DOM to isolate its styles and markup. It also initializes a base gridOptions object, which will be populated with data from Unqork.

initialize(api)

The required method for Unqork integration. The Unqork Runtime calls this method to provide the component with the api object. This is where the component gets its initial data from Unqork's state and sets up subscriptions to listen for future changes.

subscribeColumnDefs()

The subscribeColumnDefs() method listens for changes to the columnDefinitions property in the component's state. By subscribing to these changes, the method ensures the AG Grid's columns are dynamically updated to reflect the new configuration. This enables creators to use operations to change the grid's columns at runtime.

subscribeData()

Listens for changes to the value property in the component's state. By subscribing to these changes, the method ensures the AG Grid's values are dynamically updated to reflect the new configuration. This enables creators to use operations to change the grid's values at runtime.

renderGrid(document, gridOptions)

Handles the initial rendering of the AG Grid. It creates the HTML container for the grid, uses the AG Grid library (window.agGrid) to create the grid instance, and sets up a cellClicked event listener.

updateGrid(gridOptions)

A helper function that calls AG Grid's internal API to update the grid's configuration, which is used by the subscription methods to apply changes.

emitCellClickedEvent(ev)

This method is the component's output. It uses the Unqork Runtime's api.events.emit() function to send a custom event (onAgGridCellClicked) when a user clicks a cell in the grid.

This allows other components or workflows in Unqork to react to the click by using the Operations Builder.

_normalizeInput(val)

A utility method that checks if the input value is a string and, if so, parses it as JSON. This handles inconsistencies with how data might be stored in the Unqork platform.

_formatColumnDefinitions(defs)

A helper method that translates the Unqork component's input format using the key and label properties into the format that AG Grid requires (field and headerName).

Understanding the agGrid and agGridCellClicked Exports

These exports serve as the component’s manifest, providing the Unqork runtime with the necessary data to use the component.

Class

Description

agGrid

This object exports the model (the component’s data schema) and the view (the component itself). The Unqork platform uses this to configure the component's properties and render it correctly.

agGridCellClicked

This object defines a custom event. It exports a model that describes the structure of the event's payload. For example, the name and payload when a grid cell is clicked. Doing so lets other parts of the Unqork platform use and understand the event that the component emits.

Create the BYO Component Package

After the asset JavaScript and manifest.json files are complete, compress them into a BYO package.

To compile a file using Terminal (Mac) or Command Prompt (Windows):

  1. Using the command line prompt, navigate to the directory containing the agGrid.js and manifest.json files. For example, cd C:\Users\UserName\Desktop\agGrid.

  2. Execute the following command: tar -cvzf agGrid.tar.gz manifest.json agGrid.js.
    Terminal window showing commands to create a tar.gz file from project files.

The agGrid.js file and manifest.json add to the tar.gz file in the same folder they're located in.

NOTE

The steps above use the tar command and the following options:

-c: Creates a new archive.

-z: Compresses the archive using gzip.

-v: Lists the files in the command line as they are added to archive.

-f: Specifies the file name for the archived files.

Upload the BYO Operation Package

After creating the agGrid.tar.gz package, upload it to the Unqork Designer Platform using the Custom Assets Administration page:

  1. From the UDesigner homepage, click Administration.

  2. Under Assets, click Custom Assets Administration.

  3. Click + Create New. The Create Asset modal displays.

  4. Under File Upload, click or drag the BYO Operation package from your local device to the upload window.

  5. Click Scan File. The package details display.
    Create asset form for AgGrid version 1.0.0 with successful scan notification.

  6. Click Review Assets.

  7. Review the asset's details, including Components, Events, and Operations.

  8. Click Confirm & Create.

  9. Review the Library Usage Acknowledgment and Liability Agreement. Click the ☐ (checkbox) to acknowledge the agreement.

  10. Click Create Asset.

The asset package displays in the Custom Assets’ Packages list. The package's individual assets display in the Assets tab's Assets list. The assets are now available in the Module Builder for all applications in the environment.

Test the AG Grid Component

Now that the BYO AG Grid component is in the Unqork Designer Platform, test its functionality in the Module Builder and Express View. This example assumes you are configuring a Vega (2.0) module.

For this example, test the following functions:

  • AG Grid Configuration Drawer: Verify each setting is functional.

  • agGridCellClicked Event: Verify the event emits when clicking a cell in the grid.

Configure the Text Field Component

Use a Text Field component to receive the final value created by using the BYO agGridCellClicked event and SET_PROPERTY operation.

  1. In the Module Builder, drag and drop a Text Field component onto your canvas.

  2. In the Property ID field, enter output.

  3. In the Label Text field, enter Cell Clicked.

  4. Click Save Component.

Configure the Custom Component

The Custom Component contains a list of all BYO components in the environment. Select the AG Grid component, then configure it to test its settings, and the custom agGridCellClicked event.

  1. Drag and drop a Custom Component onto your canvas.

  2. In the Property ID field, enter byoAgGrid.

  3. From the Select Component drop-down, enter or select AG Grid. The component's configuration populates.

  4. Click the Add Item button three times to create a total of four objects.

  5. Configure each Object with the following:

    Object #

    Setting

    Value

    Object 1

    Key

    make

    Label

    Make

    Object 2

    Key

    model

    Label

    Model

    Object 3

    Key

    price

    Label

    Price

    Object 4

    Key

    electric

    Label

    Electric

  6. In the Value field, enter the following table data:

    [{"make":"Tesla","model":"Model Y","price":64950,"electric":true},{"make":"Ford","model":"F-Series","price":33850,"electric":false},{"make":"Toyota","model":"Corolla","price":29600,"electric":false},{"make":"Mercedes","model":"EQA","price":48890,"electric":true},{"make":"Fiat","model":"500","price":15774,"electric":false},{"make":"Nissan","model":"Juke","price":20675,"electric":false}]

Configure the byoAgGrid Event and Operation

While remaining in the configuration drawer, set up the BYO agGridCellClicked event to trigger a Set Property operation. Configure the operation to retrieve the current selected AG Grid cell’s value.

  1. Next to Events & Operations, click Edit.

  2. From the Select an Event drop-down, enter or select Cell Clicked. This is the BYO event defined in the agGrid.js  file.

  3. Click Add.

  4. Click + Add Operation.

  5. From the Operation Type drop-down, select Set Property .

  6. In the Target Key field, enter output. This sends the operation’s output to the output Text Field component.

  7. In the Property field, enter value.

  8. In the Value field, enter {{$event.payload.value}}. When the end-user clicks on a cell, this dynamic value updates to the clicked cell’s value.

  9. Click Save.

  10. Click Close.

  11. Click Save Component.

  12. Save your module. module

Your completed module looks like the following:

BYO AG Grid component interface showing cell clicked and component options.

Preview and Test the Module

Finally, test your configuration and verify that the AG Grid table displays in Express View, and the agGridCellClicked event emits the Set Property operation.

  1. Preview your module in Express View.

  2. Verify the grid displays the table data contained in the Custom Component.

  3. In the AG Grid, click on a cell.

  4. In the Cell Clicked field, verify that the value matches the cell’s value. This verifies the agGridCellClicked is emitting properly.

If the custom asset functions as intended, then it’s ready to be used by Creators in the development of Unqork applications.

If the Custom Operation generates errors or is missing features:

  1. Create a copy of the current package and its contents.

  2. Update the package's required files.

  3. Change the package's version number.

  4. Update the package by referring to the Package Management section in our BYO Best Practices article.