Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to format data before displaying it on ag-grid

I've just discovered ag-grid. I'm using it on angular2+ and loading data from api. One of fields is date, but its in ISO format. I've been trying to format it, is there any way to do it, is it possible to add pipe or some other way? Usually i do it like this {{ someISODate | date: 'dd.MM.yyyy HH:mm'}}. Do i really have to format it manually in component before displaying it? Also I was wondering if its possible to add two fields under one column. Why? Well i have column author, and in data that im getting from api i have author.firstname and author.lastname, and now I wanna display both fields in same column. Any hints or examples are more than welcomed.

columnDefs = [
    {headerName: 'Datum kreiranja', field: 'createdAt' }, //<-- wanna format it
    {headerName: 'Vrsta predmeta', field: 'type.name' },
    {headerName: 'Opis', field: 'description'},
    {headerName: 'Kontakt', field: 'client.name'},
    {headerName: 'Autor', field: 'author.firstname'}, //<-- wanna display author.lastname in same cell
    {headerName: 'Status', field: 'status.name'}
];
like image 900
Kerim092 Avatar asked Jul 23 '18 03:07

Kerim092


People also ask

How do you use a value formatter in ag-Grid?

By default, a valueFormatter will only be used for formatting the values in ag-Grid cells, and the filtering values will be generated from the underlying unformatted data. In order to format the filtering values for this column the same way as the column cell values, we need to pass the valueFormatter to the filter.

How do you show and hide columns in ag-Grid?

Just add " hide: true " in your column definition. Show activity on this post. thank you for giving answer..But.. hide: "true" this is working for hide the column from AG grid but this column appears in Toolpanel...


5 Answers

You can do this by using cellRenderer (or valueFormatter as pointed in the UPDATE) and moment library.

 {
      headerName: 'Datuk kreiranja', field: 'createdAt',
      cellRenderer: (data) => {
          return moment(data.createdAt).format('MM/DD/YYYY HH:mm')
      }
 }

If you don't want to use moment, then below is how you can do it.

cellRenderer: (data) => {
     return data.value ? (new Date(data.value)).toLocaleDateString() : '';
}

For Author field as well,

cellRenderer: (data) => {
     return data.author.firstname + ' ' + data.author.lastname;
}

Reference: ag-grid: Cell Rendering


UPDATE

As suggested by @Mariusz, using valueFormatter makes more sense in this scenario. As per documentation, Value Formatter vs Cell Renderer

value formatter's are for text formatting and cell renderer's are for when you want to include HTML markup and potentially functionality to the cell. So for example, if you want to put punctuation into a value, use a value formatter, but if you want to put buttons or HTML links use a cell renderer.

like image 161
Paritosh Avatar answered Oct 02 '22 10:10

Paritosh


You can use valueFormatter

{headerName: 'Datuk kreiranja', field: 'createdAt', valueFormatter: this.dateFormatter},

Create a small function:

dateFormatter(params) {
  return moment(params.value).format('MM/DD/YYYY HH:mm');
}
like image 20
DancingDad Avatar answered Oct 02 '22 10:10

DancingDad


First of all thanks to Paritosh. The issue I was facing is the date field I was receiving from API is on the below format

"endDateUTC":"2020-04-29T12:00:00",

I have followed Paritosh solution using cellrenderer along with moment library but the value was always formatted to today's date for some reason.

The below solution is using valueFormatter with moment library.

This is for Angular2+ version. The job is really simple

In your .ts file:

    import * as moment from 'moment';

{
    headerName: 'End Date',
    field: 'endDateUTC',
    minWidth: 80,
    maxWidth: 100,
    valueFormatter: function (params) {
        return moment(params.value).format('D MMM YYYY');
    },
},

And the output you will get is:

End date: 29 APR 2020

Please feel free to change the date format you need.

Hope this will be helpful to some one.

like image 39
Ragavan Rajan Avatar answered Oct 02 '22 09:10

Ragavan Rajan


I just want to expand on Vishwajeet's excellent answer from April 2019. Here's how I would use his code, and which import commands would be required:

    import { Component, OnInit, ViewChild, LOCALE_ID, Inject } from '@angular/core';

    constructor(@Inject(LOCALE_ID) private locale: string)
    {
    }

    columnDefs = [
        { headerName: 'Last name', field: 'lastName' },
        { headerName: 'First name', field: 'firstName' },
        { headerName: 'DOB', field: 'dob', cellRenderer: (data) => { return formatDate(data.value, 'd MMM yyyy HH:mm', this.locale); }},
        { headerName: 'Policy start', field: 'policyStartDate', cellRenderer: (data) => { return formatDate(data.value, 'd MMM yyyy HH:mm', this.locale); } },
        { headerName: 'Policy end', field: 'policyEndDate', cellRenderer: (data) => { return formatDate(data.value, 'd MMM yyyy HH:mm', this.locale); } }
    ]

And your agGrid would contain something like this:

  <ag-grid-angular 
      class="ag-theme-material" 
      [rowData]="rowData"
      [columnDefs]="columnDefs" 
  </ag-grid-angular>

This works really nicely, but I decided to move the date formatting into it's own cell renderer for a few reasons:

  1. The code above will display null values as "1 Jan 1970 01:00"
  2. You would need to repeat this code, plus the imports and @Inject, into any control which uses it.
  3. It repeats the logic each time, so if you wanted to change the date format throughout your application, it's harder to do. Also, if a future version of Angular broke that date formatting, you'd need to apply a fix for each occurrence.

So, let's move it into it's own cell renderer.

My DateTimeRenderer.ts file looks like this:

import { Component, LOCALE_ID, Inject } from '@angular/core';
import { ICellRendererAngularComp } from 'ag-grid-angular';
import { ICellRendererParams } from 'ag-grid-community';
import { formatDate } from '@angular/common';

@Component({
    selector: 'datetime-cell',
    template: `<span>{{ formatTheDate(params.value) }}</span>`
})
export class DateTimeRenderer implements ICellRendererAngularComp {

    public params: ICellRendererParams; 

    constructor(@Inject(LOCALE_ID) public locale: string) { }

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

    formatTheDate(dateValue) {
        //  Convert a date like "2020-01-16T13:50:06.26" into a readable format
        if (dateValue == null)
            return "";
        return formatDate(dateValue, 'd MMM yyyy HH:mm', this.locale);
    }

    public onChange(event) {
        this.params.data[this.params.colDef.field] = event.currentTarget.checked;
    }

    refresh(params: ICellRendererParams): boolean {
        return true;
    }
}

In my app.module.ts file, I need to import this Component:

import { DateTimeRenderer } from './cellRenderers/DateTimeRenderer';

@NgModule({
  declarations: [
    AppComponent,
    DateTimeRenderer
  ],
  imports: [
    BrowserModule,
    AgGridModule.withComponents([DateTimeRenderer])
  ],
  providers: [],
  bootstrap: [AppComponent]
})

And now, back in my Component which uses the agGrid, I can remove LOCALE_ID, Inject from this line:

import { Component, OnInit, ViewChild, LOCALE_ID, Inject } from '@angular/core';

..remove it from our constructor...

constructor()
{
}

..import our new renderer...

import { DateTimeRenderer } from './cellRenderers/DateTimeRenderer';

..and change the columnDefs to use the new renderer:

columnDefs = [
    { headerName: 'Last name', field: 'lastName' },
    { headerName: 'First name', field: 'firstName' },
    { headerName: 'DOB', field: 'dob', cellRenderer: 'dateTimeRenderer' },
    { headerName: 'Policy start', field: 'policyStartDate', cellRenderer: 'dateTimeRenderer' },
    { headerName: 'Policy end', field: 'policyEndDate', cellRenderer: 'dateTimeRenderer' }
]
frameworkComponents = {
    dateTimeRenderer: DateTimeRenderer
}

And I just need to make sure my agGrid knows about this new frameworkComponents section:

<ag-grid-angular 
      class="ag-theme-material" 
      [rowData]="rowData"
      [columnDefs]="columnDefs" 
      [frameworkComponents]="frameworkComponents"  >
  </ag-grid-angular>

And that's it.

Again, the nice thing about this is I can use this date formatter anywhere throughout my code, and all the logic is in one place.

It's just shocking that, in 2020, we actually need to write our own date formatting function for an up-to-date grid like agGrid... this really should've been included in the agGrid libraries.

like image 38
Mike Gledhill Avatar answered Oct 02 '22 09:10

Mike Gledhill


For Angular, if you want to do this without moment.js you can try something like below:

import { Component, OnInit, Inject, LOCALE_ID } from '@angular/core';
import { formatDate } from '@angular/common';

@Component({
  selector: 'app-xyz'
})
export class xyzComponent implements OnInit {

  constructor( @Inject(LOCALE_ID) private locale: string ) {
  }

  columnDefs = [

    {headerName: 'Submitted Date', field: 'lastSubmittedDate', cellRenderer: (data) => {
      return  formatDate(data.value, 'dd MMM yyyy', this.locale);
     }];

}

This component is using format date of angular/common

like image 33
Vishwajeet Avatar answered Oct 02 '22 10:10

Vishwajeet