TL;DR: Let’s see how to implement inline editing in the Syncfusion Angular Pivot Table. Inline editing lets users modify data directly within the table, updating values in real time without extra popups. This blog covers how to enable and customize inline editing for seamless data management, improving workflow efficiency and user experience.
In today’s data-driven world, presenting data clearly and interactively is crucial. The ability to seamlessly visualize and interact with data can change how users analyze and interpret information. This is where the Syncfusion Angular Pivot Table shines, with its powerful features that improve data visualization.
One standout capability is seamless inline editing, which allows users to make real-time changes within the Pivot Table. Let’s look at how the Angular Pivot Table can help with data visualization and inline editing.
The Syncfusion Angular Pivot Table is a powerful and adaptable component for complex data visualization. It provides several benefits:
One of the most appealing aspects of the Angular Pivot Table is its seamless inline editing functionality. This option allows users to edit data directly in the table, making the process more intuitive and efficient. Key benefits include:
First, we need to create the Angular Pivot Table component by following the instructions provided in the getting started guide.
The built-in inline editing feature lets you modify a cell’s value directly without an edit dialog. This feature is only available when the cell’s value originates from a single raw data. It applies to all editing modes, including normal, batch, dialog, and column commands. You can activate inline editing by setting the allowInlineEditing property in the editSettings to true.
app.component.html
<div style="margin-top: 100px;"> <ejs-pivotview #pivotview id='PivotView' [dataSourceSettings]=dataSourceSettings showFieldList='true' [showTooltip]='false' width='100%' height='500' [gridSettings]='gridSettings' [editSettings]='editSettings'></ejs-pivotview> </div>
app.component.ts
import { Component, OnInit, ViewChild } from '@angular/core'; import { RouterOutlet } from '@angular/router'; import { IDataOptions, IDataSet, PivotViewModule, FieldListService, PivotView, CellEditSettings, } from '@syncfusion/ej2-angular-pivotview'; import { GridSettings } from '@syncfusion/ej2-pivotview/src/pivotview/model/gridsettings'; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet, PivotViewModule], templateUrl: './app.component.html', styleUrl: './app.component.css', providers: [FieldListService], })
export class AppComponent implements OnInit { public dataSourceSettings: IDataOptions | undefined; public gridSettings: GridSettings | undefined; public editSettings?: CellEditSettings; @ViewChild('pivotview') public pivotObj: PivotView | undefined; getPivotData(): IDataSet[] { let pivotData: IDataSet[] = [ { Amount: 2100, Country: 'Canada', Date: 'FY 2005', Product: 'Bike', Quantity: 22, State: 'Alberta', } ]; return pivotData; } ngOnInit(): void { this.gridSettings = { columnWidth: 160, } as GridSettings; this.editSettings = { allowEditing: true, allowInlineEditing: true, } as CellEditSettings; this.dataSourceSettings = { values: [ { name: 'Sold', caption: 'Units Sold' }, { name: 'Amount', caption: 'Sold Amount' }, ], formatSettings: [{ name: 'Amount', format: 'C' }], columns: [ { name: 'Year' }, { name: 'Order_Source', caption: 'Order Source' }, ], dataSource: this.getPivotData(), rows: [{ name: 'Country' }, { name: 'Products' }], filters: [], expandAll: false, enableSorting: true, }; } }
Refer to the following GIF image.
If the cell’s value is derived from more than one raw data source, an editing popup opens, allowing you to edit the raw data for a specific cell. However, we can restrict the editing dialog using the drillThrough event if you wish to edit these cells like inline editing.
The values in the Pivot Table can then be changed and updated using inline editing when double-clicking the value cells for the combinational data source. It allows you to modify both the specified Pivot Table cell value and the underlying data information at the sample level.
Refer to the following code example.
app.component.html
<div style="margin-top: 100px;"> <ejs-pivotview #pivotview [dataSourceSettings]=dataSourceSettings showFieldList='true' [showTooltip]='false' width='100%' height='500' allowDrillThrough='true' [gridSettings]='gridSettings' (drillThrough)="drillThrough($event)"></ejs-pivotview> </div>
app.component.ts
import { Component, OnInit, ViewChild } from '@angular/core'; import { RouterOutlet } from '@angular/router'; import { IDataOptions, IDataSet, PivotViewModule, FieldListService, PivotView } from '@syncfusion/ej2-angular-pivotview'; import { GridSettings } from '@syncfusion/ej2-pivotview/src/pivotview/model/gridsettings'; import { NumericTextBox } from '@syncfusion/ej2-inputs'; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet, PivotViewModule], templateUrl: './app.component.html', styleUrl: './app.component.css', providers: [FieldListService] }) export class AppComponent implements OnInit { public dataSourceSettings: IDataOptions | undefined; public gridSettings: GridSettings | undefined; public indexObject: any; public eventArgs: any; public actualText: string | undefined; public updatedData: any; @ViewChild('pivotview') public pivotObj: PivotView | undefined; getPivotData(): IDataSet[] { let pivotData: IDataSet[] = [ { 'Sold': 31, 'Amount': 52824, 'Country': 'France', 'Products': 'Mountain Bikes', 'Year': 'FY 2015', 'Quarter': 'Q1' }, { 'Sold': 51, 'Amount': 86904, 'Country': 'France', 'Products': 'Mountain Bikes', 'Year': 'FY 2015', 'Quarter': 'Q2' }, { 'Sold': 90, 'Amount': 153360, 'Country': 'France', 'Products': 'Mountain Bikes', 'Year': 'FY 2015', 'Quarter': 'Q3' }, { 'Sold': 25, 'Amount': 42600, 'Country': 'France', 'Products': 'Mountain Bikes', 'Year': 'FY 2015', 'Quarter': 'Q4' }]; return pivotData; } drillThrough(args: any) { args.cancel = true; this.eventArgs = args; this.eventArgs.currentTarget.children[0].style.display = 'none'; this.actualText = this.eventArgs.currentCell.actualText; this.indexObject = Object.keys(this.eventArgs.currentCell.indexObject); if (!document.body.querySelector('#' + this.pivotObj?.element.id + 'inline')) { let div = document.createElement('input'); div.id = this.pivotObj?.element.id + 'inline'; args.currentTarget.appendChild(div); let numeric: NumericTextBox = new NumericTextBox({ value: args.currentCell.value, change: this.onChange.bind(this), blur: this.onBlur.bind(this), }); numeric.appendTo(div); this.eventArgs.currentCell.value = this.updatedData; numeric.focusIn(); } } onChange(args: any) { let differenceOfValue: number; let splitRawData: number; if (args.previousValue < args.value) { differenceOfValue = args.value - args.previousValue; } else { differenceOfValue = args.previousValue - args.value; } splitRawData = differenceOfValue / this.eventArgs.rawData.length; for (let i: number = 0; i < this.eventArgs.rawData.length; i++) { if (args.previousValue < args.value) { this.eventArgs.rawData[i][this.actualText as string] = this.eventArgs.rawData[i][this.actualText as string] + splitRawData; } else { this.eventArgs.rawData[i][this.actualText as string] = this.eventArgs.rawData[i][this.actualText as string] - splitRawData; } } } onBlur(args: any) { for (let k: number = 0; k < this.indexObject.length; k++) { if (this.pivotObj) { this.pivotObj.engineModule.data[this.indexObject[k]] = this.eventArgs.rawData[k]; } } this.pivotObj?.setProperties( { dataSourceSettings: { dataSource: this.pivotObj?.engineModule.data } }, true ); this.pivotObj?.engineModule.updateGridData(this.pivotObj?.dataSourceSettings); if (this.pivotObj) { this.pivotObj.pivotValues = this.pivotObj?.engineModule.pivotValues; } this.updatedData = args.value; } ngOnInit(): void { this.gridSettings = { columnWidth: 160 } as GridSettings; this.dataSourceSettings = { values: [ { name: 'Sold', caption: 'Units Sold' }, { name: 'Amount', caption: 'Sold Amount' }, ], formatSettings: [{ name: 'Amount', format: 'C' }], columns: [ { name: 'Year' }, { name: 'Order_Source', caption: 'Order Source' }, ], dataSource: this.getPivotData(), rows: [{ name: 'Country' }, { name: 'Products' }], filters: [], expandAll: false, enableSorting: true }; } }
That’s it. Double-click any value cell in the Angular Pivot Table to update the values using inline editing instead of the editing dialog.
Before customization:
After customization:
When we double-click a value cell in the Angular Pivot Table, the drillThrough event is triggered before the editing popup is displayed. That event allows us to restrict the editing popup. To modify and update the cell value, we need to insert an input element in it. In the above code example, we have added the Syncfusion Angular Numeric Textbox component in the value cell.
Then, we used the Angular Numeric TextBox’s change and blur events to modify and update the data source. In the change event, the raw data for that Pivot value is updated in response to the changed data. If the modified data exceeds the previous value, the difference is divided and added evenly to all the underlying raw data. If the modified data is less than the previous value, the difference is divided and subtracted equally from all the underlying raw data. The blur event refreshes the Angular Pivot Table with the modified data source.
For more details, refer to the inline editing in the Angular Pivot Table GitHub demo.
Thanks for reading! The Syncfusion Angular Pivot Table improves both data visualization and user interaction. Its seamless inline editing capabilities significantly improve the user experience by enabling real-time, in-context data updates. Integrating this feature allows you to streamline your data workflows, reduce errors, and make more informed decisions. Start using this versatile component today to transform your data visualization and fully utilize its advanced features.
For existing customers, the newest version of Essential Studio® is available for download from the License and Downloads page. If you are not a Syncfusion customer, try our 30-day free trial to check out the available features.
If you have questions, contact us through our support forum, support portal, or feedback portal. We are always happy to assist you!