Sorting rows in ag-grid based on custom data displayed by cellRenderer

My goal is to enable column sorting on cell data that includes custom HTML elements. I understand that I might need to create a custom function to override the default sorting behavior and refer it to the raw values instead of the rendered HTML output.

Despite consulting the ag-grid documentation at https://www.ag-grid.com/javascript-grid-sorting/, I am unable to find clear instructions on how to achieve this. The solution mentioned on the page seems relevant, but the explanation and sample code provided don't offer much help in understanding the implementation process. It appears that utilizing a comparator is necessary, yet in the example concerning dateComparator, it's unclear how the parameters (date1, date2) are utilized within the custom function.

Below, you can find some sample code demonstrating the issue, including a comparator function that gets called when clicking on the column header to sort the rows.

var columnDefs = [{ field: 'rank' }, { headerName: 'custom', cellRenderer: customCellRenderer, comparator: customNumberComparator }];

var rowData = [{ 'rank': 1, 'customData': '3.64' }, { 'rank': 2, 'customData': '-1.56' }, { 'rank': 3, 'customData': '11.21' }, { 'rank': 4, 'customData': '0.36' }, { 'rank': 5, 'customData': '45.1' }, { 'rank': 6, 'customData': '-34.2' }];

function customCellRenderer () {}

customCellRenderer.prototype.init = function ( params ) {
    this.eGui = document.createElement ( 'span' );
    this.eGui.textContent = params.data.customData + '%';

    if ( parseFloat( params.data.customData ) < 0 ) {
        this.eGui.setAttribute( 'style', 'color: red');
    } else {
        this.eGui.setAttribute( 'style', 'color: green');
    }
}

customCellRenderer.prototype.getGui = function () {
    return this.eGui;
}

// TEST FUNCTION TO OUTPUT params data
function customNumberComparator ( params ) {
  const log = document.getElementById('log');
  
  if (params === undefined ) {
      log.textContent = 'undefined';
    } else {
      log.textContent = params.data;
    }
}

var gridOptions = {
    columnDefs: columnDefs,
    rowData: rowData,
    enableSorting: true
}

document.addEventListener("DOMContentLoaded", function() {
    // lookup the container we want the Grid to use
    var eGridDiv = document.querySelector('#myGrid');

    // create the grid passing in the div to use together with the columns & data we want to use
    new agGrid.Grid(eGridDiv, gridOptions);
}
<script src="https://unpkg.com/ag-grid/dist/ag-grid.min.js"></script>

<div id="myGrid" style="height: 150px;width:500px" class="ag-theme-fresh"></div>

<span id="log">customNumberComparator output here</span>

Answer №1

In response to my own query:

The resolution lies in the valueGetter attribute of the column definition, which involves a personalized function call to provide cells with a value that can be utilized for sorting.

I have included some code below to illustrate how adding valueGetter: PercentValueGetter to the columnDefs, followed by a PercentValueGetter function, will be invoked when the

There are also options such as valueSetter, valueFormatter, and valueParser available for further customization.

https://www.ag-grid.com/javascript-grid-value-setters/

var columnDefs = [{ field: 'rank' }, { headerName: 'custom', cellRenderer: customCellRenderer, valueGetter: PercentValueGetter }];

var rowData = [{ 'rank': 1, 'customData': '3.64' }, { 'rank': 2, 'customData': '-1.56' }, { 'rank': 3, 'customData': '11.21' }, { 'rank': 4, 'customData': '0.36' }, { 'rank': 5, 'customData': '45.1' }, { 'rank': 6, 'customData': '-34.2' }];

function customCellRenderer () {}

customCellRenderer.prototype.init = function ( params ) {
    this.eGui = document.createElement ( 'span' );
    this.eGui.textContent = params.data.customData + '%';

    if ( parseFloat( params.data.customData ) < 0 ) {
        this.eGui.setAttribute( 'style', 'color: red');
    } else {
        this.eGui.setAttribute( 'style', 'color: green');
    }
}

customCellRenderer.prototype.getGui = function () {
    return this.eGui;
}

function PercentValueGetter ( params ) {
  return params.data.customData;
}

var gridOptions = {
    columnDefs: columnDefs,
    rowData: rowData,
    enableSorting: true
}

document.addEventListener("DOMContentLoaded", function() {
    // lookup the container we want the Grid to use
    var eGridDiv = document.querySelector('#myGrid');

    // create the grid passing in the div to use together with the columns & data we want to use
    new agGrid.Grid(eGridDiv, gridOptions);
});
<script src="https://unpkg.com/ag-grid/dist/ag-grid.min.js"></script>

<div id="myGrid" style="height: 150px;width:500px" class="ag-theme-fresh"></div>

Answer №2

If you prefer, instead of using OP's solution, you have the option to utilize the comparator field and provide your own function. The third and fourth parameters in that function correspond to the nodes, allowing you to access any column (see documentation). I've substituted the valueGetter with a custom comparator:

var columnDefs = [{ field: 'rank' }, { headerName: 'custom', cellRenderer: customCellRenderer, comparator: customComparator }];

var rowData = [{ 'rank': 1, 'customData': '3.64' }, { 'rank': 2, 'customData': '-1.56' }, { 'rank': 3, 'customData': '11.21' }, { 'rank': 4, 'customData': '0.36' }, { 'rank': 5, 'customData': '45.1' }, { 'rank': 6, 'customData': '-34.2' }];

function customCellRenderer () {}

customCellRenderer.prototype.init = function ( params ) {
    this.eGui = document.createElement ( 'span' );
    this.eGui.textContent = params.data.customData + '%';

    if ( parseFloat( params.data.customData ) < 0 ) {
        this.eGui.setAttribute( 'style', 'color: red');
    } else {
        this.eGui.setAttribute( 'style', 'color: green');
    }
}

customCellRenderer.prototype.getGui = function () {
    return this.eGui;
}

function customComparator(_valueA, _valueB, nodeA, nodeB) {
    return Number(nodeA.data.customData) - Number(nodeB.data.customData)
}

var gridOptions = {
    columnDefs: columnDefs,
    rowData: rowData,
    enableSorting: true
}

document.addEventListener("DOMContentLoaded", function() {
    // lookup the container we want the Grid to use
    var eGridDiv = document.querySelector('#myGrid');

    // create the grid passing in the div to use together with the columns & data we want to use
    new agGrid.Grid(eGridDiv, gridOptions);
});
<script src="https://unpkg.com/ag-grid/dist/ag-grid.min.js"></script>

<div id="myGrid" style="height: 150px;width:500px" class="ag-theme-fresh"></div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to assign values to object variables in JavaScript

I'm currently working on a project in AngularJS that involves reading data from files. The goal is to assign the content to a variable within an object if the file is read successfully, otherwise, assign "NA" to the same variable. function customer($ ...

Bringing life to web pages through captivating animations when showing and hiding div elements, utilizing the power

After extensive research on various online platforms, including stackoverflow, I unfortunately couldn't find a suitable solution to my problem. However, with the invaluable assistance of you all, I managed to successfully implement a code for my proje ...

Ways to customize MuiPaper-root styling within material-table

Currently utilizing a material-table from https://material-table.com/. An issue I am encountering is the inability to change the table's border-radius and shadow using the 'option feature'. Upon inspecting the table, it appears that the ra ...

What is the process for extracting data from latitude and longitude in order to generate a marker on Google Maps using a script

I have an HTML input text and want to pass coordinates to create a marker on Google maps. Check out the code here: jsfiddle.net/#&togetherjs=r3M9Kp7ff7 What is the best way to transfer this data from HTML to JavaScript? <label for="latitude">L ...

After toggling the class, Jquery will no longer select the button

I am having an issue with my jQuery code where I have a button that, when clicked, should switch classes from #testButton to .first or .second. The image toggle shows that the first click works fine and toggles the image, but the second click does not seem ...

Having issues with images not loading and receiving a 401 error with the API while using Vite in a production build

While working on my React project with Vite, I've encountered a few challenges during the production build process. Everything seems to be running smoothly when I use npm run dev, but when I try to build the project using npm run build and then previ ...

The issue persists where Tailwind Inline color decorators are unable to function properly alongside CSS variables

In my current project using Tailwind CSS with CSS variables for styling, I have noticed a peculiar issue. The color previewers/decorators that usually appear when defining a color are not showing up in my class names. These previewers are quite helpful in ...

How can I retrieve the OptionID value upon click?

How can I retrieve the value of OptionID when the Add button (.plus-link) is clicked? Each list item may contain a dropdown select menu or not. <ul> <li> <div class="menux"> <div class="text-block"> ...

Triggering functions when the mouse wheel is in motion

I am new to utilizing javascript and jquery, and my knowledge is limited at the moment. I am attempting to create a script that will trigger different functions based on the direction of mouse wheel movements in a way that works across various programs. Ca ...

Tips for eliminating flicker upon the initial loading of a webpage caused by dynamic changes in CSS styles through JavaScript

Struggling with the load order of my CSS and JavaScript... Currently, I have a div with a blue background that is styled to appear sliced diagonally. However, upon initial page load (or CTRL+SHIFT+R), there's a brief moment where the slice effect doe ...

When Vue 3 is paired with Vite, it may result in a blank page being rendered if the

Issue with Rendering Counter in Vite Project After setting up a new project using Vite on an Arch-based operating system, I encountered a problem when attempting to create the simple counter from the Vue documentation. The element does not render as expec ...

Strategies for formatting JSON data in a controller

As someone who is new to AngularJS and JSON, I am facing an issue when trying to filter out unnecessary fields in the JSON data. In my controller, I have the following code snippet: var data = $scope.choices; // This is an array var datav = (JSON.stringi ...

A link is not allowed to be a child of another link

An issue arises in a React.js application Warning: validateDOMNesting(...): <a> cannot be nested under another <a>. Refer to Element > a > ... > a for more information. What is the significance of this warning? How can it be avoided ...

Unable to utilize ES6 syntax for injecting a service

I am encountering some issues while trying to implement a service into a controller using ES6 syntax. CategoriesService.js export default class CategoriesService { constructor() { this.getCategories = function ($q) { var deferred ...

retrieve the data-initial-value's value through JavaScript

Hello, I am currently attempting to retrieve the text from this input field but all I'm getting is an empty value. <input type="text" class="quantumWizTextinputPaperinputInput exportInput" jsname="YPqjbf" autocomplete= ...

Replacing invalid characters using jQuery

My input field (type=password) is restricted to only accept certain characters. Below is the code snippet: $(document).ready(function() { $('#nguestpass, #nguestps, #nuserpass, #nuserps, #nadminpass, #nadminps').bind('keyup').bind(& ...

Having trouble getting Angular 2 animations to fade in

I've been trying to figure out how to make the html fadeIn for hours. Every time ngFor displays it, the opacity stays at 1 immediately, without fading in. FadingOut works fine, but the fadeIn effect is not working as expected. @Component({ selector:& ...

Conceal information on-the-fly using React

I am seeking a way to dynamically hide irrelevant items based on their tags. This functionality should only be applied to tags with a "taglevel" higher than 1. For instance, if I select the tag "books," only the tags "adventure" and "classic" should be d ...

Removing a modal div element in React after navigating

import React, { useState } from "react"; import { useNavigate } from "react-router-dom"; import axios from "axios"; import Cookies from "js-cookie"; const LoginPage = () => { const [email, setEmail] = useState( ...

Add both single (' ') and double (" ") quotes within the `document.querySelector` code

Given an array of attributes like the following: let elementsArray = [ '[name="country_code"]', '[name="user_tel_code"]', '[name="countryCode"]' ]; If I aim to iterate through them using a ...