Multiple rows edition

This section describes how to update, delete or restore more than one row at a time.

Live example

Multiple rows edition live example.

Edition actions

Before exploring the edition actions, do not forget to allow edition and enable the edition mode.

Remember that the edition mode will display all the UI elements for editing rows.

We start defining some editable columns.

multiple-rows-edition.component.html
<dike-grid id="grid-multiple-rows-edition" height="600px" #grid="dkgGrid"
    allowEdition
    [editionMode]="gridProperties.editionMode">
    
    <dike-grid-column
        fieldName="employeeId"
        headerText="Employee Id"
        dataType="Text"
        width="350">
    </dike-grid-column>

    <dike-grid-column
        fieldName="completeNameGroup"
        headerText="Complete Name">

        <dike-grid-column
            fieldName="firstName"
            headerText="Name"
            dataType="Text"
            width="150"
            editable
            [editionSettings]="{ required: true }">
        </dike-grid-column>

        <dike-grid-column
            fieldName="lastName"
            headerText="Surname"
            dataType="Text"
            width="150"
            editable
            [editionSettings]="{ required: true }">
        </dike-grid-column>
    </dike-grid-column>

    <dike-grid-column
        fieldName="gender"
        headerText="Gender"
        dataType="Binary"
        width="110"
        editable
        [editionSettings]="{ required: true, options: [ { label: 'M', value: 'male' }, { label: 'F', value: 'female' } ] }"
        [editionTemplate]="genderEdition">
    </dike-grid-column>

    <dike-grid-column
        fieldName="age"
        headerText="Age"
        dataType="Numeric"
        contentAlign="center"
        width="100"
        editable
        [editionSettings]="{ required: true }">
    </dike-grid-column>

    <dike-grid-column
        fieldName="email"
        headerText="Email"
        dataType="Text"
        width="300"
        editable
        [editionSettings]="emailEditionSettings"
        [editionTemplate]="emailEdition">
    </dike-grid-column>

    <dike-grid-column
        fieldName="hireDate"
        headerText="Hire Date"
        dataType="Date"
        editable
        [editionSettings]="{ required: true }">
    </dike-grid-column>
</dike-grid>

<ng-template #genderEdition let-control="control" let-options="options">
    <mat-radio-group class="flex flex-row justify-between" [formControl]="control">
      <mat-radio-button *ngFor="let option of options" [value]="option.value">{{ option.label }}</mat-radio-button>
    </mat-radio-group>
</ng-template>

<ng-template #emailEdition let-control="control">
    <mat-form-field floatLabel="never">
        <input matInput
            type="text"
            [formControl]="control"
            autocomplete="off">
        <mat-icon matSuffix>email</mat-icon>
    </mat-form-field>
</ng-template>

We have configured the following features:

  1. All the columns are editable except for the Employee Id column.

  2. All editable columns are required, and we have set templates for the Gender and Email columns.

  3. You can toggle to the edition mode from the Floating Configuration Panel.

When the DikeGrid is in the edition mode, it shows an icon (three vertical dots) at the left of every row. When you click on this icon, it will show a contextual menu with the edition operations per row.

At the same time, the DikeGrid shows an icon (three horizontal dots) in the header at the left of the first visible column header. When you click on this icon, it will show a contextual menu with the edition operations for multiple rows.

Editing rows

Let us start editing some rows by double-clicking on them. This action will display the edition templates for each editable column.

The DikeGrid allows you to have up to 10 rows in edition state by default, but you can change this value by providing the corresponding value.

You can change the maximum rows in the edition state value by providing an Injection Token or at the grid level.

Variable
Description

MAX_ROWS_IN_EDITION

This value affects all your DikeGrid instances that live under the place you give your Injection Token.

DikeGridEditionSettings { maxRowsInEdition?: number };

Providing at this level only affects the DikeGrid instance that receives the value.

Let us provide the MAX_ROWS_IN_EDITION token:

editing.module.ts
@NgModule({
  providers: [
    { provide: MAX_ROWS_IN_EDITION, useValue: 5 }
  ]
})
export class EditingModule { }

When you reach the maximum number of rows in the edition state, the DikeGrid will show you a message indicating it.

Saving rows

Once you have made some changes to some rows, you can save these rows by clicking on the Save option from the contextual menu in the header.

Be aware that the DikeGrid will enable the Save option if all rows in the edition state are valid and at least one is not pristine. Therefore, the DikeGrid will save those valid rows which are not pristine.

After updating rows, the DikeGrid changes the status of every row to the Modified value.

Please, open the live example to test the Save operation.

Canceling edition

When you have some rows in the edition state, the first enabled option in the contextual menu is Cancel.

Clicking on the Cancel option in the context menu will cancel the edition of all the rows in the edition state.

If you have made some changes, you will lose those changes by canceling the edition.

Deleting rows

To delete rows from the DikeGrid UI, you must enable the selection operation. Therefore, you can delete only the selected rows from the UI.

The Remove option appears in the contextual menu if you allow the user to select rows, and the DikeGrid will enable it only when the user has selected one row at least.

Let us provide the corresponding input property to enable the selection operation.

multiple-rows-edition.component.html
<dike-grid id="grid-multiple-rows-edition" height="600px" #grid="dkgGrid"
    [allowSelection]="gridProperties.allowSelection">
</dike-grid>

You can open the Floating Configuration Panel and click on the Allow Selection checkbox.

Now the context menu shows the Remove option.

If the user has selected rows in the edition state, the DikeGrid will not delete them.

Reverting changes

You can undo changes from the modified or deleted rows. Therefore, you have to change the view from the UI to display only modified or deleted rows.

Edition filters

If you open the context menu, you can see an option called Edition Filter, and under this option, you will find the edition subsets options.

The DikeGrid will take the user to the edition view by clicking on these edition subsets options.

Option - Editing

Clicking on this menu option will display only the rows in the edition state. Showing only the rows editing is helpful when you have grouped the rows, for instance, because the rows in the edition state could be in different groups.

As you can see, the icon in the header changes to a pencil icon (instead of the three horizontal dots), indicating that you are viewing only the rows in the edition state.

Option - Modified

This menu option shows only those rows that have suffered changes. When you navigate to the modified-rows view, you will see an icon with a badge at the left of every row. The badge indicates how many times the user has changed the row.

You click on the icon with a badge to revert the changes in the row. This action will take the row to its immediate previous state.

You can click on the icon with a badge until the row reaches its initial state. The initial state corresponds to the row state equals to Read value.

If you have enabled the selection operation, you can select more than one row and take them to their immediate previous state by clicking on the Restore option from the contextual menu.

Once again, see how the DikeGrid changes the icon to indicate that you are viewing the modified rows.

Option - Removed

This menu option shows only the subset of rows that corresponds to the deleted rows. When you are in the deleted-rows view, you will see an icon with a badge at the left of every row. Again, the badge indicates how many times the user has changed the row, but this time the last action corresponds to the deletion operation.

If the badge displays a number greater than one means that the row has suffered changes before deleting it.

The DikeGrid changes the icon in the header to indicate that you are viewing the deleted rows.

If you have enabled the selection operation, you can select more than one row and restore them by clicking on the Restore option from the contextual menu.

Option - Back

You can display the standard view by clicking on the Back option.

You can filter every edition subset of rows by typing values in a filterable column. The values you enter in the Edition Filters view are independent of the values in the standard view.

Edition Toolbar

All the edition actions for multiple rows are available through the Edition Toolbar. When you display the Edition Toolbar, the DikeGrid hides the contextual menu in the header.

If you want to use the Edition Toolbar in the live example, open the Floating Configuration Panel and click on the Edition Toolbar checkbox.

When displaying the Edition Toolbar, the DikeGrid still shows the icon in the header but does not show the contextual menu.

Customizing the Edition Toolbar

You can change the appearance of the Edition Toolbar by modifying its height, alignment, or position. You can also change the size of its items.

For further details, see the Grid Structure - Edition Toolbar section.

DikeGrid Edition API

You can perform the edition actions using the edition API.

Before using the API, we have to retrieve the DikeGrid instance from the component's view.

<dike-grid id="grid-multiple-rows-edition" height="600px" #grid="dkgGrid">
</dike-grid>

The following method operates over multiple rows edition.

Method
Description

updateRowsInEdition()

This method takes all valid rows which are not pristine and saves their changes.

removeRows()

It removes from the given rows only those rows that are not in the edition state and do not have the Deleted value in their row status.

cancelRowsInEdition()

It cancels the current edition state for every row, losing all the changes you have made.

restoreRows()

It takes the given rows to their immediate previous row state. It filters the given rows taking only those modified or deleted rows.

setEditionFilter()

It displays the corresponding subset of rows editing. Invoking this method is equivalent to clicking on the contextual menu's Editing, Modified, or Removed options.

Since this method changes the view of the DikeGrid, you should have provided the allowEdition and editionMode input properties.

cancelEditionFilter()

Invoking this method, the DikeGrid will show the standard view. It is equivalent to clicking on the Back option of the contextual menu.

For further details, see the DikeGridEdition definition.

It is enough to set the input property called allowEdition to use the edition API.

To see the API in action, consider the following additions to the UI:

<div class="mt-2 flex flex-row flex-wrap items-center justify-around">
    <div class="flex-none w-56 flex flex-col m-2 items-center">
        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onSaveRows()">Save rows
        </button>

        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onCancelEdition()">Cancel Edition
        </button>
    </div>

    <div class="flex-none w-56 flex flex-col m-2 items-center">
        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onRemoveRows()">Remove rows
        </button>
    </div>

    <div class="flex-none w-60 flex flex-col m-2 items-center">
        <mat-radio-group class="flex-none w-56 flex flex-row justify-between" [formControl]="rowTypecontrol">
            <mat-radio-button value="modified">Modified</mat-radio-button>
            <mat-radio-button value="removed">Removed</mat-radio-button>
          </mat-radio-group>

        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onRestoreRows()">Restore rows
        </button>
    </div>
</div>

<dike-grid id="grid-multiple-rows-edition" height="600px" #grid="dkgGrid">
</dike-grid>

The previous definition generates the following output:

We have added the following buttons:

  1. Save rows. This action updates the rows in edition state. Remember that the DikeGrid will save only those valid rows that are not pristine.

  2. Cancel Edition. Clicking on this button will cancel the edition state for every row editing.

  3. Remove rows. Click on this button to delete the selected rows. The DikeGrid will not remove the rows in the edition state.

  4. Restore rows. This action works over the modified or deleted rows. Therefore, you select which type of rows the DikeGrid will restore.

Edition events

The edition events for multiple rows are the same when working over one row. Regarding the various rows edition, the DikeGrid emits an array of rows instead of one row.

We listen to these events:

<dike-grid id="grid-multiple-rows-edition" height="600px" #grid="dkgGrid"
    (editionRowChange)="onEditionRowChange($event)"
    (updateRowChange)="onUpdateRowChange($event)"
    (cancelRowEditionChange)="onCancelRowEditionChange($event)"
    (removeRowChange)="onRemoveRowChange($event)"
    (restoreRowChange)="onRestoreRowChange($event)">
    
</dike-grid>

You can also listen to these events from the DikeGridEdition instance

Please, open the dev console to see the events' output.

Blocking the UI

When you click on any edition option from the contextual menu, the DikeGrid shows the Processing Indicator to block its UI until the updating ends.

For further details on blocking the DikeGrid UI, see the Grid Structure - Waiting Indicator section.

You can avoid the DikeGrid displaying the Processing Indicator by providing a false value through the related Injection Token or at the grid level.

You can provide any of the following Injection Tokens depending on the edition action:

Edition action
Injection Token

Save

WAIT_FOR_MULTIPLE_ROWS_UPDATE

Cancel

WAIT_FOR_MULTIPLE_ROWS_CANCELATION

Remove

WAIT_FOR_MULTIPLE_ROWS_DELETION

Restore

WAIT_FOR_MULTIPLE_ROWS_RESTORATION

If you want to apply the value for a particular DikeGrid instance, provide the corresponding variable through the DikeGridEditionsSettings reference:

Edition action
Variable

Save

waitForMultipleRowsUpdate

Cancel

waitForMultipleRowsCancelation

Remove

waitForMultipleRowsDeletion

Restore

waitForMultipleRowsRestoration

Let us provide the WAIT_FOR_MULTIPLE_ROWS_CANCELATION Injection Token to avoid displaying the Processing Indicator when canceling the edition.

editing.module.ts
@NgModule({
  providers: [
    { provide: WAIT_FOR_MULTIPLE_ROWS_CANCELATION, useValue: false }
  ]
})
export class EditingModule { }

Summary

Apart from saving changes for one row, you can update multiples rows simultaneously. However, be aware that you must enable the selection operation for deleting and restoring multiple rows.

You must navigate to the edition view for restoring rows by clicking on the corresponding edition filter. Every row shows an icon with a badge conveying how many times the row has suffered changes.

You can perform the edition actions for multiple rows using the edition API. Moreover, the DikeGrid emits the related event for every edition action.

Complete code for this section

<div class="mt-2 flex flex-row flex-wrap items-center justify-around">
    <div class="flex-none w-56 flex flex-col m-2 items-center">
        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onSaveRows()">Save rows
        </button>

        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onCancelEdition()">Cancel Edition
        </button>
    </div>

    <div class="flex-none w-56 flex flex-col m-2 items-center">
        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onRemoveRows()">Remove rows
        </button>
    </div>

    <div class="flex-none w-60 flex flex-col m-2 items-center">
        <mat-radio-group class="flex-none w-56 flex flex-row justify-between" [formControl]="rowTypecontrol">
            <mat-radio-button value="modified">Modified</mat-radio-button>
            <mat-radio-button value="removed">Removed</mat-radio-button>
          </mat-radio-group>

        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onRestoreRows()">Restore rows
        </button>
    </div>
</div>

<dike-grid id="grid-multiple-rows-edition" height="600px" #grid="dkgGrid"
    [displayRowId]="gridProperties.displayRowId"
    [gridElevation]="gridProperties.matElevation"
    [gridElevationValue]="gridProperties.elevationValue"
    [striped]="gridProperties.stripeRows"
    [verticalRowLines]="gridProperties.verticalRowLines"

    allowEdition
    [editionMode]="gridProperties.editionMode"
    [allowSelection]="gridProperties.allowSelection"
    [editionToolbar]="gridProperties.displayEditionToolbar"
    [editionToolbarRowHeight]="gridProperties.editionToolbarHeight"
    [editionToolbarItemHeight]="gridProperties.edtitionToolbarItemHeight"
    [editionToolbarPosition]="gridProperties.editionToolbarPosition"
    [editionToolbarAlignment]="gridProperties.editionToolbarAlignment"

    (editionRowChange)="onEditionRowChange($event)"
    (updateRowChange)="onUpdateRowChange($event)"
    (cancelRowEditionChange)="onCancelRowEditionChange($event)"
    (removeRowChange)="onRemoveRowChange($event)"
    (restoreRowChange)="onRestoreRowChange($event)"

    [datasource]="dkgDataSource">
    
    <dike-grid-column
        fieldName="employeeId"
        headerText="Employee Id"
        dataType="Text"
        width="350">
    </dike-grid-column>

    <dike-grid-column
        fieldName="completeNameGroup"
        headerText="Complete Name">

        <dike-grid-column
            fieldName="firstName"
            headerText="Name"
            dataType="Text"
            width="150"
            editable
            [editionSettings]="{ required: true }">
        </dike-grid-column>

        <dike-grid-column
            fieldName="lastName"
            headerText="Surname"
            dataType="Text"
            width="150"
            editable
            [editionSettings]="{ required: true }">
        </dike-grid-column>
    </dike-grid-column>

    <dike-grid-column
        fieldName="gender"
        headerText="Gender"
        dataType="Binary"
        width="110"
        editable
        [editionSettings]="{ required: true, options: [ { label: 'M', value: 'male' }, { label: 'F', value: 'female' } ] }"
        [editionTemplate]="genderEdition">
    </dike-grid-column>

    <dike-grid-column
        fieldName="age"
        headerText="Age"
        dataType="Numeric"
        contentAlign="center"
        width="100"
        editable
        [editionSettings]="{ required: true }">
    </dike-grid-column>

    <dike-grid-column
        fieldName="email"
        headerText="Email"
        dataType="Text"
        width="300"
        editable
        [editionSettings]="emailEditionSettings"
        [editionTemplate]="emailEdition">
    </dike-grid-column>

    <dike-grid-column
        fieldName="hireDate"
        headerText="Hire Date"
        dataType="Date"
        editable
        [editionSettings]="{ required: true }">
    </dike-grid-column>
</dike-grid>

<ng-template #genderEdition let-control="control" let-options="options">
    <mat-radio-group class="flex flex-row justify-between" [formControl]="control">
      <mat-radio-button *ngFor="let option of options" [value]="option.value">{{ option.label }}</mat-radio-button>
    </mat-radio-group>
</ng-template>

<ng-template #emailEdition let-control="control">
    <mat-form-field floatLabel="never">
        <input matInput
            type="text"
            [formControl]="control"
            autocomplete="off">
        <mat-icon matSuffix>email</mat-icon>
    </mat-form-field>
</ng-template>

Last updated