What is CRUD

    CRUD is an acronym in computer programming that stands for the CREATE, READ, UPDATE, DELETE operations that can be performed against a data collection. In computer world, talking about CRUD applications, is a main difference compared to applications that provide read-only data to users.

    Angular CRUD

    While talking about Angular CRUD, or CRUD operations in Angular, it is important to note that the data storage is on a remote server. The Angular application can not directly access the data layer, so it needs to communicate with it through a Web API that provides endpoints for the CRUD operations, i.e.:

    API Operation HTTP methods
    "api/entities" READ all entities GET
    "api/entities/id" READ the entity with corresponding id GET
    "api/entities/update" UPDATE the entity with corresponding id PUT / PATCH
    "api/entities/create" CREATE a new entity POST
    "api/entities/delete" DELETE the entity with corresponding id DELETE

    Notice that the CRUD operations also map conceptually to the HTTP methods that are used to communicate with APIs over HTTP.

    The entire code that will work with the above mentioned API can be abstracted in an Angular service. Such a service is injectable and can be reused by any component that needs to perform CRUD operations against the same database. A good practice is to write such service as generic as possible, thus making it suitable to be reused in many components, and against different servers as well.

    A generic example of such service will look like this:

    @Injectable()
    export class CRUDService {
      /** See https://angular.io/api/common/http/HttpClient */
      constructor(private http: HttpClient) { }
    
      /** Gets all entities from server */
      public getData() {
          return this.http.get(`${this.serverURL}\api\entities`);
      }
    
      /** Gets entity with corrresponding id */
      public getRecord(id) {
          return this.http.get(`${this.serverURL}\api\entities\${id}`);
      }
    
      /** Creates entity from body */
      public add(entity) {
          return this.http.post(`${this.serverURL}\api\entities\create`, entity);
      }
    
      /* Updates entity with data from body */
      public update(entity) {
          return this.http.put(`${this.serverURL}\api\entities\update`, entity);
      }
    
      /** Deletes the corresponding entity */
      public delete(entity) {
          return this.http.delete(`${this.serverURL}\api\entities\delete`, entity);
      }
    }
    

    What the above service is missing is configuration for filtering/sorting/paging, etc. Depending on the exact API implementation of the endpoints, requests to the server may need optional parameters to handle filtering/sorting/paging for you. See our Remote Data Operations for demos accompanied with code examples.

    For more examples and guidance, refer to the HTTP Services tutorial in the official Angular documentation.

    CRUD Operations with Grid

    Enabling CRUD in the Grid means providing UI for the users to perform these CRUD operations from within the grid. This is quite easy - the Grid provides Cell Editing, Row Editing, Row Adding and Row Deleting UI out of the box, and powerful API to do this on your own. Next, we want to take the result of each editing action and communicate it to the corresponding method in our CRUD service, thus preserving all changes to the original database. By completing this, we may say the grid is CRUD enabled.

    This section is written as HOW-TO tutorial on enabling CRUD operations in Grid, accompanied by code snippets that you can take and copy paste in your code.

    How to

    Let's first enable the rowEditing behavior, bring the UI we need for the editing actions, benefiting from the IgxActionStrip (see more about the IgxActionStrip), and attach event handlers:

    <igx-grid 
        primaryKey="ID"
        [rowEditable]="true"
        (rowAdded)="rowAdded($event)"
        (rowDeleted)="rowDeleted($event)"
        (rowEditDone)="rowEditDone($event)">
    
      <igx-action-strip #actionstrip>
          <igx-grid-editing-actions [addRow]="true"></igx-grid-editing-actions>
      </igx-action-strip>
    

    In the Angular component, inject the data service using DI. Now we are ready to use the service to do full CRUD operations against our data layer:

    constructor(private crudService: CRUDService) { }
    
    public rowDeleted(event: IRowDataEventArgs) {
        this._crudService.delete(event.data).subscribe((rec) => {
            // notification or do any adittional handling
            this.snackbar.open(`Row with ID of ${rec.ID} was deleted.`);
        });
    }
    
    public rowAdded(event: IRowDataEventArgs) {
        this._crudService.add(event.data);
    }
    
    public rowEditDone(event: IGridEditDoneEventArgs) {
        this._crudService.update(event.newValue);
    }
    

    In the above example, we only call the corresponding methods and pass the data that is read from the event arguments. Most API endpoints will return the updated/added/deleted entity, which indicates that the request was successful.

    A good practice is to add validation, notifying the users that all actions have been completed successfully or that an error has occurred. In such case, you may want to pass handlers for the error and complete notifications too:

    this._crudService.delete(event.data).subscribe({
        next: (data: any) => {
          console.log('success');
        },
        error: err => {
          console.log(err);
        },
        complete: () => {
          console.log('Complete notification')
        }
    });
    
    Note

    The above examples are based on the default grid UI for editing actions. Another valid approach is if you provide your own external UI. In such case, responding to user interactions with the UI should work with the grid editing API (make sure the grid has a primaryKey set). See API section for reference.

    Note

    Make sure to follow best practices and prevent any differences in your local data compared to the server database. For example - you may decide to first make a request to the server to delete a record, but if the request fails, do not delete the data on the local grid data:

    this._crudService.delete(event.data).subscribe({
        next: (data: any) => {
          this.grid.getRowByKey(event.data[this.grid.primaryKey]).delete();
        },
        error: err => {
          console.log(err); // notify and don't delete the grid row
        }
    });
    

    Demo

    See the demo that was built following the guidance. Play around with it and try the examples for customization to fit your scenario in the best possible way.

    Customizations

    The rich Grid API allows you to customize the editing process in almost any way in order to fit your needs. This includes, but is not limited to:

    • Batch Editing: Enable Batch Editing to batch all updates, and commit everything with single request.
    • Templating: Add templates for cell editing, or use your own external UI for row/cell editing, row adding and row deleting.
    • Events: Monitor the editing flow and react accordingly. Attach event handlers for all events emitted during editing, will allow you to do:
      • data validation per cell
      • data validation per row
      • prompt user for expected type of input
      • cancel further processing, based on business rules
      • manual committing of the changes
    • Rich API

    Batch Editing

    • Enable Batch Editing to keep your updates on the client, and commit all of them with single request. Batch updating is enabled bysetting batchEditing option to true:
    <igx-grid [batchEditing]="'true'" ...>
    

    Go to Batch Editing for more details and demo samples.

    Templates

    You can see and learn more about default cell editing templates in the general editing topic.

    If you want to provide a custom template which will be applied when a cell is in edit mode, you can make use of the igxCellEditor directive. To do this, you need to pass an ng-template marked with the igxCellEditor directive and properly bind your custom control to the cell.editValue:

    <igx-column field="class" header="Class" [editable]="true">
        <ng-template igxCellEditor let-cell="cell" let-value>
            <igx-select class="cell-select" [(ngModel)]="cell.editValue" [igxFocus]="true">
                <igx-select-item *ngFor="let class of classes" [value]="class">
                    {{ class }}
                </igx-select-item>
            </igx-select>
        </ng-template>
    </igx-column>
    

    For more information and demos, see the Cell Editing topic.

    Events

    The grid exposes a wide array of events that provide greater control over the editing experience. These events are fired during the Row Editing and Cell Editing lifecycle - when starting, committing or canceling the editing action.

    Event Description Arguments Cancellable
    rowEditEnter If rowEditing is enabled, fires when a row enters edit mode IGridEditEventArgs true
    cellEditEnter Fires when a cell enters edit mode (after rowEditEnter) IGridEditEventArgs true
    cellEdit If value is changed, fires just before a cell's value is committed (e.g. by pressing Enter) IGridEditEventArgs true
    cellEditDone If value is changed, fires after a cell has been edited and cell's value is committed IGridEditDoneEventArgs false
    cellEditExit Fires when a cell exits edit mode IGridEditDoneEventArgs false
    rowEdit If rowEditing is enabled, fires just before a row in edit mode's value is committed (e.g. by clicking the Done button on the Row Editing Overlay) IGridEditEventArgs true
    rowEditDone If rowEditing is enabled, fires after a row has been edited and new row's value has been committed. IGridEditDoneEventArgs false
    rowEditExit If rowEditing is enabled, fires when a row exits edit mode IGridEditDoneEventArgs false

    Go to Events for more details and demo samples.

    Editing API

    Updating data in the grid is achieved through methods exposed both by the grid:

    and update method exposed by the IgxGridCell and IgxGridRow instances:

    // Through the grid methods
    this.grid.updateRow(newData, rowKey);
    this.grid.updateCell(newData, rowKey, columnField);
    this.grid1.deleteRow(0);
    this.grid.addRow(data);
    
    // Through the methods exposed by cell/row
    this.grid.getCellByColumn(rowIndex, columnField).update(newData);
    this.grid.getCellByKey(rowKey, columnField).value = newData;
    this.grid.getRowByKey(rowID).update(newData);
    this.grid.getRowByKey(rowID).delete();
    

    More details and information about using the grid API can be found in the Cell Editing CRUD Operations section.

    Takeaway

    Enabling CRUD in a robust way is major milestone for any data-driven application. In order to streamline the entire process, we've built the IgxGrid with the CRUD capabilities in mind, providing out-of-the-box UI and flexible APIs. How will this benefit you? It will save you lots of time when implementing CRUD against any database out there. And when we talk about modern-day data-driven apps, it all comes down to robustness, speed, and flexibility.

    API References