Streamline Data Management with Inline Editing in Angular Pivot Table

syncfusionsyncfusion
8 min read

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.

Why should you choose the Syncfusion Angular Pivot Table?

The Syncfusion Angular Pivot Table is a powerful and adaptable component for complex data visualization. It provides several benefits:

  • Dynamic data analysis: With its drag-and-drop interface, users can easily pivot, slice, and dice data.

  • Rich data visualization: It supports various chart types, conditional formatting, and calculated fields.

  • Performance: It is designed for high performance and can efficiently handle large datasets, ensuring smooth interactions.

  • Customization: Highly customizable to meet the specific needs of your app.

Seamless inline editing in Angular Pivot Table

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:

  • Real-time updates: Inline editing allows users to update data instantly, eliminating the need for additional popups. This ensures that data is current and accurate, allowing for more responsive and agile decision-making.

  • Enhanced user experience: The ability to edit data directly in the table increases user interaction and engagement. Users can concentrate on analyzing and updating data from a single interface, eliminating the need to switch between views or apps.

  • Streamlined workflow: By integrating inline editing, you can reduce the steps required for data entry and correction, resulting in a more streamlined and efficient workflow. This is especially useful in environments where quick adjustments are frequently required.

How to implement inline editing in the Angular Pivot Table?

First, we need to create the Angular Pivot Table component by following the instructions provided in the getting started guide.

Built-in option

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.

Built-in inline editing option in the pivot table

Built-in inline editing option in the pivot table

Convert the built-in editing dialog into an inline editing option

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:

Built-in editing dialog in the pivot table

Built-in editing dialog in the pivot table

After customization:

Converting the built-in editing dialog into an inline editing option in the Angular Pivot Table

Converting the built-in editing dialog into an inline editing option in the Angular Pivot Table

How does the above customization work?

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.

GitHub reference

For more details, refer to the inline editing in the Angular Pivot Table GitHub demo.

Conclusion

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!

0
Subscribe to my newsletter

Read articles from syncfusion directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

syncfusion
syncfusion

Syncfusion provides third-party UI components for React, Vue, Angular, JavaScript, Blazor, .NET MAUI, ASP.NET MVC, Core, WinForms, WPF, UWP and Xamarin.