Column Rendering in Angular Grid Component
17 Sep 202524 minutes to read
In the Syncfusion® Angular Grid, column rendering provides the ability to precisely control how data is presented. This allows manual column definition, automatic column generation, and dynamic customization of data presentation. With column rendering, data can be displayed exactly as needed, offering extensive possibilities for organizing and showcasing information within the grid.
The column definitions serve as the data source schema in the grid. Grid operations such as sorting, filtering, and grouping are performed based on column definitions. The field property of the grid column is necessary to map the data source values to the grid columns.
- If the column
field
is not specified in the dataSource, the column values will be empty.- If the
field
name contains a dot operator, it is considered complex binding.- The
field
property must be defined for a Template column to perform CRUD or data operations such as filtering and searching.Define columns manually
To define columns manually in the grid, use the e-columns
element to define the columns and represent each column with its respective properties such as field, headerText, type, and width set accordingly. This allows customization of the column’s behavior and appearance based on requirements.
Here’s an example code snippet that demonstrates how to define columns manually in the Syncfusion Angular Grid:
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule } from '@syncfusion/ej2-angular-grids'
import { PageService, SortService, FilterService, GroupService } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit } from '@angular/core';
import { data } from './datasource';
@Component({
imports: [
GridModule
],
providers: [PageService,
SortService,
FilterService,
GroupService],
standalone: true,
selector: 'app-root',
template: `<ejs-grid [dataSource]='data'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' width=90></e-column>
<e-column field='CustomerID' headerText='Customer ID' width=120></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Right' format='C2' width=90></e-column>
<e-column field='OrderDate' headerText='Order Date' textAlign='Right' format='yMd' width=120></e-column>
</e-columns>
</ejs-grid>`
})
export class AppComponent implements OnInit {
public data?: object[];
ngOnInit(): void {
this.data = data;
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Auto generated columns
The Grid automatically generates columns when the columns declaration is empty or undefined while initializing the grid. All the columns in the dataSource are bound as grid columns.
The following code snippet enables auto-generated columns in the Syncfusion Grid:
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit } from '@angular/core';
import { data } from './datasource';
@Component({
imports: [
GridModule
],
standalone: true,
selector: 'app-root',
template: `<ejs-grid [dataSource]='data'>
</ejs-grid>`
})
export class AppComponent implements OnInit {
public data?: object[];
ngOnInit(): void {
this.data = data;
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
- When columns are auto-generated, the column type is determined from the first record of the dataSource.
- For large datasets, auto-generating columns can result in performance issues. In such cases, it is recommended to specify the columns manually in the columns property during initialization or use column virtualization by setting enableColumnVirtualization property to true.
Set isPrimaryKey for auto generated columns when editing is enabled
When editing is enabled in the grid, setting a primary key for auto-generated columns may be necessary to uniquely identify each row for operations such as updating or deleting data. This can be achieved using the isPrimaryKey property of the column object through the dataBound event.
By setting isPrimaryKey
to true for an auto-generated column in the Syncfusion Grid, it can be specified as the primary key column, which uniquely identifies each row when editing is enabled.
Here is an example code snippet that shows how to set a primary key for an auto-generated column when editing is enabled:
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit, ViewChild } from '@angular/core';
import { GridComponent, EditSettingsModel, EditService, Column, PageService } from '@syncfusion/ej2-angular-grids';
import { data } from './datasource';
@Component({
imports: [
GridModule
],
standalone: true,
selector: 'app-root',
template: `<ejs-grid #grid [dataSource]='data' allowPaging='true' [editSettings]='editSettings' (dataBound)="dataBound()">
</ejs-grid>`,
providers: [EditService, PageService]
})
export class AppComponent implements OnInit {
public data?: object[];
public editSettings: EditSettingsModel;
@ViewChild('grid')
public grid?: GridComponent;
ngOnInit(): void {
this.data = data;
this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true };
}
dataBound() {
(((this.grid as GridComponent).columns[0]) as Column).isPrimaryKey = true;
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
If the column field name is known, the getColumnByField method can be used to retrieve the column object. Then, the isPrimaryKey
property can be set to true for that column, as demonstrated in the code snippet below:
onDataBound(event: any): void {
const column: ColumnModel = this.grid.getColumnByField('OrderID');
column.isPrimaryKey = true;
}
Set column options to auto generated columns
To configure column options such as type, format, and width for auto-generated columns in Syncfusion Grid, use the dataBound event of the Grid component. This event is triggered after the data has been bound to the Grid. By handling this event, the desired column options for the auto-generated columns can be specified.
Here’s an example of how to set column options for auto-generated columns using the dataBound
event:
In the following example, width
is set for the OrderID column, date type
is set for the OrderDate column, and format
is set for the Freight and OrderDate columns.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit, ViewChild } from '@angular/core';
import { GridComponent } from '@syncfusion/ej2-angular-grids';
import { data } from './datasource'
@Component({
imports: [
GridModule
],
standalone: true,
selector: 'app-root',
template: `<ejs-grid #grid [dataSource]='data' (dataBound)="dataBound()">
</ejs-grid>`
})
export class AppComponent implements OnInit {
public data?: object[];
@ViewChild('grid') public grid?: GridComponent;
ngOnInit(): void {
this.data = data;
}
dataBound() {
for (const cols of (this.grid as GridComponent).columns) {
if (cols.field === 'OrderID') {
cols.width = 120;
}
if (cols.field === 'OrderDate') {
cols.type = 'date';
cols.format = 'yMd';
}
if (cols.field === 'Freight') {
cols.format = 'P2';
}
}
(this.grid as GridComponent).refreshColumns();
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Dynamic column generation
The Syncfusion Grid component allows dynamic generation of columns at runtime based on the provided data. This feature is useful when displaying data with varying columns depending on specific requirements or dynamic data sources.
Using ngFor directive
To create dynamically generated columns in the Syncfusion Grid component using the ngFor directive, first define an array of column objects in the component.ts file. Each column object should include a field and headerText property, which will be used to bind the corresponding properties of the e-column component.
Here is an example for dynamically generating columns in the grid using the ngFor directive:
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule } from '@syncfusion/ej2-angular-grids'
import { PageService, SortService, FilterService, GroupService } from '@syncfusion/ej2-angular-grids'
import { Component, NgIterable, OnInit } from '@angular/core';
import { data } from './datasource';
import { ColumnModel } from '@syncfusion/ej2-angular-grids';
@Component({
imports: [
GridModule
],
providers: [PageService,
SortService,
FilterService,
GroupService],
standalone: true,
selector: 'app-root',
template: `<ejs-grid #grid [dataSource]='data'>
<e-columns>
<e-column *ngFor="let column of columns" [field]="column.field" [headerText]="column.headerText"></e-column>
</e-columns>
</ejs-grid>`
})
export class AppComponent implements OnInit {
public data?: object[];
public columns?: NgIterable<ColumnModel> | null | undefined;
ngOnInit(): void {
this.data = data;
this.columns = [
{ field: 'OrderID', headerText: 'Order ID' },
{ field: 'CustomerID', headerText: 'Customer ID' },
{ field: 'Freight', headerText: 'Freight' },
{ field: 'ShipCountry', headerText: 'ShipCountry' }
];
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
The data source or columns can be changed dynamically in the Syncfusion Grid by using the changeDataSource method. For more information, please refer to this section.
Using valueAccessor property
Dynamic column generation using value accessor allows access and manipulation of the display data values in a grid column. By using the valueAccessor property of a grid column, the display value of the column can be customized based on the data.
To use the valueAccessor
property, define the column with the property and provide a function that will return the formatted value. The function receives two arguments:
- field: represents the data field of the column.
- data: represents the data record for the corresponding row.
In the provided code, the currencyFormatter function takes the Freight value of the data object, appends the Euro symbol to it, and returns the formatted string. The concatenateFields function concatenates the ShipCity and ShipRegion values of the data object and returns the combined string.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit } from '@angular/core';
import { data } from './datasource';
@Component({
imports: [
GridModule
],
standalone: true,
selector: 'app-root',
template: `<ejs-grid #grid [dataSource]='data' [height]='315'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' width=100></e-column>
<e-column field='CustomerID' headerText='Customer ID' width=120></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Right'
[valueAccessor]='currencyFormatter' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130 [valueAccessor]='concatenateFields' ></e-column>
</e-columns>
</ejs-grid>`
})
export class AppComponent implements OnInit {
public data?: object[];
public currencyFormatter = (field: string, valueAccessordata: object, column: object) => {
return '€' + (valueAccessordata as any)["Freight"];
}
public concatenateFields = (field: string, valueAccessordata: object, column: object) => {
return (valueAccessordata as any)[field] + ' - ' + (valueAccessordata as any)["ShipRegion"];
}
ngOnInit(): void {
this.data = data;
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
The
valueAccessor
function can have performance implications if used to access a large number of data records or to perform complex data manipulations. To avoid performance issues, enable the virtualization feature while using the valueAccessor property. This ensures that only the visible rows are rendered, resulting in faster rendering times.
Display array type columns
The Grid component allows easy binding of an array of objects to a column using the valueAccessor property. This property allows customization of how the data is displayed in the column.
For example, consider a column named Name that contains an array of two objects, FirstName and LastName. The valueAccessor
property can be used to join these two objects and bind them to the column.
This will display the concatenated value of FirstName and LastName in the Full Name column of the grid. Here’s an example of how this can be achieved:
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit } from '@angular/core';
import { stringData } from './datasource';
@Component({
imports: [
GridModule
],
standalone: true,
selector: 'app-root',
template: `<ejs-grid #grid [dataSource]='data' [height]='315'>
<e-columns>
<e-column field='EmployeeID' headerText='Employee ID' textAlign='Right' width=90></e-column>
<e-column field='Name' headerText='Full Name' [valueAccessor]= 'getConcatenatedNames' width=120></e-column>
<e-column field='Title' headerText='Title' width=150></e-column>
</e-columns>
</ejs-grid>`
})
export class AppComponent implements OnInit {
public data?: object[];
public getConcatenatedNames = (field: string, data: object) => {
return (data as any)[field as string].map((s: { FirstName: string, LastName: string }) => {
return s.LastName || s.FirstName;
}).join(' ');
}
ngOnInit(): void {
this.data = stringData;
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Expression column
An expression column in the Grid can be achieved by using the valueAccessor property. The valueAccessor
property allows definition of a function that calculates the value for the expression column based on the values of other columns.
In this example, there is a grid with columns Food Name, Protein, Fat, and Carbohydrate. An expression column called Calories Intake is added that calculates the total calories for each row based on the values of Protein, Fat, and Carbohydrate columns.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit } from '@angular/core';
import { foodInformation } from './datasource';
@Component({
imports: [
GridModule
],
standalone: true,
selector: 'app-root',
template: `<ejs-grid [dataSource]='data' [height]='315'>
<e-columns>
<e-column field='FoodName' headerText='Food Name' width=150></e-column>
<e-column field='Protein' headerText='Protein' textAlign='Right' width=120></e-column>
<e-column field='Fat' headerText='Fat' textAlign='Right' width=80></e-column>
<e-column field='Carbohydrate' headerText='Carbohydrate' textAlign='Right' width=120></e-column>
<e-column headerText='Calories Intake' textAlign='Right' [valueAccessor]='totalCalories' width=150></e-column>
</e-columns>
</ejs-grid>`
})
export class AppComponent implements OnInit {
public data?: object[];
public totalCalories = (field: string, data: { Protein: number, Fat: number, Carbohydrate: number }, column: Object): number => {
return data.Protein * 4 + data.Fat * 9 + data.Carbohydrate * 4;
}
ngOnInit(): void {
this.data = foodInformation;
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Display serial number
To display serial numbers in the grid for every row, use the rowDataBound event. The rowDataBound
event is triggered for each row in the grid when the data is bound to the grid.
Within the event handler, the pagesize and currentPage index can be obtained from the grid’s pageSettings property. Using these values, the serial number can be calculated based on the page size, current page, and row index. Finally, the calculated serial number can be set as the innerHTML of the corresponding row cell.
Here is an example code snippet that demonstrates how to display serial numbers in a Syncfusion Grid using the rowDataBound
event:
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule,PageService } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit, ViewChild } from '@angular/core';
import { data } from './datasource';
import { RowDataBoundEventArgs, EditSettingsModel, GridComponent, PageSettingsModel, } from '@syncfusion/ej2-angular-grids';
@Component({
imports: [
GridModule
],
providers:[PageService],
standalone: true,
selector: 'app-root',
template: `<ejs-grid #grid [dataSource]='data' (rowDataBound)='rowDataBound($event)' [editSettings]='editSettings' allowPaging="true" [pageSettings]="pageSettings">
<e-columns>
<e-column field='S.No' textAlign='Center' width=120></e-column>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' width=120></e-column>
<e-column field='CustomerID' headerText='Customer ID' width=140></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Right' format='C' width=120></e-column>
<e-column field='OrderDate' headerText='Order Date' textAlign='Right' format='yMd' width=140></e-column>
</e-columns>
</ejs-grid>`,
})
export class AppComponent implements OnInit {
public data?: object[];
public editSettings?: EditSettingsModel;
public pageSettings?: PageSettingsModel;
@ViewChild('grid')
public grid?: GridComponent;
ngOnInit(): void {
this.data = data;
this.editSettings = {
allowEditing: true,
allowAdding: true,
allowDeleting: true,
};
this.pageSettings = { pageSize: 8 };
}
rowDataBound({row}: RowDataBoundEventArgs) {
if(row){
var rowIndex = parseInt(row.getAttribute('aria-rowIndex') as string);
var currentPageNumber = (this.grid as GridComponent).pageSettings.currentPage;
var pageSize = (this.grid as GridComponent).pageSettings.pageSize;
var startIndex = ((currentPageNumber as number) - 1) * (pageSize as number);
(row.querySelector('.e-rowcell') as Element).innerHTML = (
startIndex + rowIndex
).toString();
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Complex data binding
The Syncfusion Grid component allows achievement of complex data binding by using the dot (.) operator in the column.field. This feature is particularly useful when dealing with nested or complex data structures.
Using local data
To enable complex data binding in the Grid component using local data, use the dot (.) operator in the field
property of the column. Here is an example of how to achieve complex data binding using local data:
In the following example, the nested Employee object’s FirstName and LastName properties are bound using the dot (.) operator.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit } from '@angular/core';
import { complexData } from './datasource';
@Component({
imports: [
GridModule
],
standalone: true,
selector: 'app-root',
template: `<ejs-grid #grid [dataSource]='data' [height]='315'>
<e-columns>
<e-column field='EmployeeID' headerText='Employee ID' textAlign='Right' width=120></e-column>
<e-column field='Name.FirstName' headerText='First Name' width=120></e-column>
<e-column field='Name.LastName' headerText='Last Name' width=120></e-column>
<e-column field='Title' headerText='Title' width=150></e-column>
</e-columns>
</ejs-grid>`
})
export class AppComponent implements OnInit {
public data?: object[];
ngOnInit(): void {
this.data = complexData;
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Using remote data
To enable complex data binding in the Grid component using remote data, add the expand query to the query property of the Grid to eager load the complex data. Here is an example of how to achieve complex data binding using remote data:
In the following example, the expand
query is used to load the nested Employee object’s City property using the dot (.) operator.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit } from '@angular/core';
import { DataManager, ODataV4Adaptor, Query } from '@syncfusion/ej2-data';
@Component({
imports: [
GridModule
],
standalone: true,
selector: 'app-root',
template: `<ejs-grid #grid [dataSource]='data' allowPaging='true' [query]='query' [height]='315'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' width=100></e-column>
<e-column field='CustomerID' headerText='Customer ID' width=120></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130 ></e-column>
<e-column field='Employee.City' headerText='City' width=130 ></e-column>
</e-columns>
</ejs-grid>`,
})
export class AppComponent implements OnInit {
public data: DataManager = new DataManager({
adaptor: new ODataV4Adaptor(),
crossDomain: true,
url: 'https://services.odata.org/V4/Northwind/Northwind.svc/Orders/',
});
public query = new Query().expand('Employee');
ngOnInit(): void { }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Complex data binding with list of array of objects
The Syncfusion Grid supports complex data binding with lists of arrays of objects. This feature allows binding of complex data with multiple levels of nested objects and arrays to the Grid.
The following example shows how to set complex field for data source having array of objects:
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit } from '@angular/core';
import { complexData } from './datasource';
@Component({
imports: [
GridModule
],
standalone: true,
selector: 'app-root',
template: `<ejs-grid #grid [dataSource]='data' [height]='315'>
<e-columns>
<e-column field='EmployeeID' headerText='Employee ID' textAlign='Right' width=120></e-column>
<e-column field='Names.0.FirstName' headerText='First Name' width=120></e-column>
<e-column field='Names.0.LastName' headerText='Last Name' width=120></e-column>
<e-column field='Title' headerText='Title' width=150></e-column>
</e-columns>
</ejs-grid>`
})
export class AppComponent implements OnInit {
public data?: object[];
ngOnInit(): void {
this.data = complexData;
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to set complex column as foreign key column
The Syncfusion Grid component provides the ability to set complex columns as foreign key columns. This allows display of related data from a foreign data source based on the complex column value.
The following example demonstrates how to set the Employee.EmployeeID column as a foreign key column, and display the FirstName column from the foreign data:
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, ForeignKeyService } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit } from '@angular/core';
import { data, employeeData } from './datasource';
@Component({
imports: [
GridModule
],
providers: [ForeignKeyService],
standalone: true,
selector: 'app-root',
template: `<ejs-grid #grid [dataSource]='data' [height]='315'>
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' width=100></e-column>
<e-column field='Employee.EmployeeID' headerText='Employee Name'
width=120 foreignKeyValue='FirstName' foreignKeyField='EmployeeID' [dataSource]='employeeData'></e-column>
<e-column field='Freight' headerText='Freight' textAlign='Right' width=80></e-column>
<e-column field='ShipCity' headerText='Ship City' width=130 ></e-column>
</e-columns>
</ejs-grid>`
})
export class AppComponent implements OnInit {
public data?: object[];
public employeeData?: object[];
ngOnInit(): void {
this.data = data;
this.employeeData = employeeData;
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));