Data Binding and Loading from JSON in Angular Grid

Created: 27 Feb 2019

In many cases, the data source that you are using to populate the Angular Grid component may have different format than the one used internally by the grid. To solve this, you will need to bind the data fields from the custom data source to the ones used by the grid. In this article, you will learn how to load data from a JSON file into the grid and match the data fields.

TreeGrid component is part of IntegralUI Web
a suite of UI Components for development of web apps

If you have any questions, don't hesitate to contact us at support@lidorsystems.com

The example shows a grid that is populated using a JSON file as a data source, with custom data fields in use. Templates for columns and cells are changed to use the new fields set in the data source.

Angular Grid Data Binding

Each object used in angular grid has a set of predefined field names. Depending on the object, there are similarities but also some differences. You can override these names with your own by providing an object to the dataFields property, which internally will map the default field names with the new one. In this way, you can load data from your data source, without changing its format.

You don't have to provide names for all data fields, only for those that are already in use by the grid objects, which you want override. Once this is set, you can use them in templates for columns, rows and cells.

Column Data Binding

The column object holds all settings for grid columns. This object has the following field names:

     columnFields = {
        aggregation: 'aggregation',
        allowDrag: 'allowDrag',
        allowDrop: 'allowDrop',
        allowFilter: 'allowFilter',
        allowGrouping: 'allowGrouping',
        allowResize: 'allowResize',
        canSelect: 'canSelect',
        comparer: 'comparer',
        contentAlignment: 'contentAlignment',
        editorType: 'editorType',
        editorSettings: 'editorSettings',
        filterParams: 'filterParams',
        fixed: 'fixed',
        fixedWidth: 'fixedWidth',
        footerAlignment: 'footerAlignment',
        footerText : 'footerText',
        headerAlignment: 'headerAlignment',
        headerText : 'headerText',
        icon: 'icon',
        id : 'id',
        minWidth: 'minWidth',
        maxWidth: 'maxWidth',
        selected: 'selected',
        style: 'style',
        visible: 'visible',
        width: 'width'
    }
                    

For example, if your data source uses different names for column id, editor, text, width, etc. you can create an object stating the new names:

public gridFields: any = {
    column: {
        contentAlignment: 'alignContent', 
        editorType: 'content',
        headerAlignment: 'alignHeader', 
        headerText: 'title',
        id: 'columnID',
        width: 'size'
    },
    row: {
        cells: 'items',
        id: 'nodeID',
        expanded: 'isExpanded',
        pid: 'parentID',
        rows: 'children',
        text: 'description'
    },
    cell: {
        cid: 'columnID',
        text: 'description',
        value: 'itemValue'
    }
}
                            
<div class="app-block" #application>
    <iui-treegrid [appRef]="applicationRef" [controlStyle]="gridStyle" [dataFields]="gridFields" [columns]="columns" [rows]="rows" [showFooter]="false" #treegrid>
        <ng-template let-column [iuiTemplate]="{ type: 'header' }">
            <span class="trg-dfjson-label">{{column.title}}</span>
        </ng-template>
        <ng-template let-cell [iuiTemplate]="{ type: 'cell' }">
            <span class="trg-dfjson-label">{{cell.description}}</span>
        </ng-template>
    </iui-treegrid>
</div>
                            

As you can see from column template, the title field is in use as replacement for header text.

Row Data Binding

The row object contains all settings for the gird rows. The following field names are in use:

     rowFields = {
        allowDrag: 'allowDrag',
        allowDrop: 'allowDrop',
        allowFocus: 'allowFocus',
        canSelect: 'canSelect',
        cells: 'cells',
        content: 'content',
        enabled: 'enabled',
        expanded: 'expanded',
        fixed: 'fixed',
        gid : 'gid',
        hasChildren: 'hasChildren',
        icon: 'icon',
        id : 'id',
        pid : 'pid',
        rows: 'rows',
        selected: 'selected',
        style: 'style',
        text : 'text',
        value: 'value',
        visible: 'visible'
    }
                    

If rows in your data source have different names, you can map them and override the default ones by providing an object:

public gridFields: any = {
    column: {
        contentAlignment: 'alignContent', 
        editorType: 'content',
        headerAlignment: 'alignHeader', 
        headerText: 'title',
        id: 'columnID',
        width: 'size'
    },
    row: {
        cells: 'items',
        id: 'nodeID',
        expanded: 'isExpanded',
        pid: 'parentID',
        rows: 'children',
        text: 'description'
    },
    cell: {
        cid: 'columnID',
        text: 'description',
        value: 'itemValue'
    }
}
                            

In this example, the names for row id, pid, cells it contains, child rows, etc are changed to the ones used in the JSON file (see below the content of this file).

Note If your data source arranges rows and objects in different format, during loading you may need to create a function that converts the source data objects to the ones used by angular Grid. Meaning, if you have a row where cells are an array of strings (plain values that are not objects), because the grid for cells accepts only objects, you will need to set these strings as part of the cell object.

Cell Data Binding

For cell objects, the following data fields are in use:

     cellFields = {
        allowEdit: 'allowEdit',
        cid: 'cid',
        enabled: 'enabled',
        rid: 'rid',
        selected: 'selected',
        style: 'style',
        text : 'text',
        value: 'value'
    }
                    

We mentioned above in the note that angular grid accepts only cell objects. The grid cell cannot be a simple value, like an integer, decimal or a string. It must be an object where these values are set.

The most important field is the cid field, which means column identifier. This field connects the cell with the column where it is displayed. If you reorder columns during run-time, change their visibility or in any way change the column structure, this field ensures that the cell will always appear under specified column. Even if you reorder cell objects within the row, the cell will appear correctly. So it is of great importance to set this field in your data source, or apply it during loading process. You can use a different name if you want.

public gridFields: any = {
    column: {
        contentAlignment: 'alignContent', 
        editorType: 'content',
        headerAlignment: 'alignHeader', 
        headerText: 'title',
        id: 'columnID',
        width: 'size'
    },
    row: {
        cells: 'items',
        id: 'nodeID',
        expanded: 'isExpanded',
        pid: 'parentID',
        rows: 'children',
        text: 'description'
    },
    cell: {
        cid: 'columnID',
        text: 'description',
        value: 'itemValue'
    }
}
                            
<div class="app-block" #application>
    <iui-treegrid [appRef]="applicationRef" [controlStyle]="gridStyle" [dataFields]="gridFields" [columns]="columns" [rows]="rows" [showFooter]="false" #treegrid>
        <ng-template let-column [iuiTemplate]="{ type: 'header' }">
            <span class="trg-dfjson-label">{{column.title}}</span>
        </ng-template>
        <ng-template let-cell [iuiTemplate]="{ type: 'cell' }">
            <span class="trg-dfjson-label">{{cell.description}}</span>
        </ng-template>
    </iui-treegrid>
</div>
                            

In this example, the cell cid, text and value fields are set with different names in the JSON file. The cell template in this example is simple, only displays a single text line. However, in other examples like grid with custom cell templates, you may use more data fields

How to Load Data into the Grid from a JSON file

Finally, the JSON file that is used to populate the angular Grid component has the following format:

private loadFromJSON(){
    let self = this;

    // Use HTTP service to get data from the specified JSON file
    self.http.get("./assets/file.json").subscribe((data: Array) => {
        // Suspend the grid layout from updates, to increase performance
        self.treegrid.suspendLayout();

        // Load data into the grid
        self.treegrid.loadData(data, null, self.gridFields.row, false);

        // Resume and update the grid layout
        self.treegrid.resumeLayout();
    });
}
                            
[
    { 
        "nodeID": 1, 
        "items": [{ "columnID":  2, "description":  "Theme Park Construction" }, { "columnID":  3 }, { "columnID":  4, "description":  "In Progress" } ],
        "children": [
            { 
                "nodeID":  11,
                "parentID": 1,
                "items": [{ "columnID":  2, "description":  "Site Preparations" }, { "columnID":  3 }, { "columnID":  4, "description":  "Open" }, { "columnID":  5, "description":  "Steven Beck" } ],
                "children": [

                // . . .
                // 
                // You can find the full content of this file in sample project on StackBlitz: https://stackblitz.com/edit/integralui-treegrid-data-fields-json
                            

To load this file, you can use angular http service. Once the file is loaded, it is a good practice to first suspend the grid layout from any updates (this will increase performance), load the data into the grid using the loadData method and then resume and update the grid layout.

The loadData method allows you to load data into the grid on demand. If parent object is specified (in case of a TreeGrid component), the data objects are added as its children. You can also specify the object that holds custom names for grid rows and whether the data format is a flat list or a tree hierarchy.

Conclusion

When you have a data source in a different format than the one used by the angular Grid, you can use the built-in feature of IntegralUI Grid or TreeGrid component that allows you to map the names of objects from the data source to the ones used by the grid. Once the data binding is set, you can populate the grid from a remote or local data source.

The TreeGrid component is part of IntegralUI Web.

Newsletter


Sign-up to our newsletter and you will receive news on upcoming events, latest articles, samples and special offers.
Name: Email: *
*By checking this box, I agree to receive a newsletter from Lidor Systems in accordance with the Privacy Policy. I understand that I can unsubscribe from these communications at any time by clicking on the unsubscribe link in all emails.