Developers of enterprise web applications that need to display data in grids are faced with a dilemma. Do you use plain HTML tables, which are simple and easy to build, but tired and featureless (especially since you know users will compare them to Google Sheets)? Or do you try again to find that elusive, free, open-source (but reliable) datagrid tool that will give you the performance, features, and support you need? Oh, and page bloat is always an issue...
Enter Wijmo FlexGrid, a mature, fully supported data grid. It’s now over five years old and, at version 5, it’s feature-rich, incredibly fast, and has a tiny code footprint.
FlexGrid features an Angular wrapper that simplifies the work required to create the Angular components you need, with support for all versions from Angular 2 through Angular 9. We will use Angular 8 in this tutorial.
Using Wijmo FlexGrid with Angular 8
To see how easy it is to use Wijmo FlexGrid tables in an Angular 8 application, we’ll start with a simple Angular component containing a data-bound HTML table. Once the basic version works, we’ll alter the code and switch to Wijmo FlexGrid.
Assuming node.js has been installed, use the Node Package Manager (npm) to create an Angular 8 application using the angular.io local setup. Open a command shell/terminal and type:
npm install -g @angular/cli
ng new my-app
Select defaults N for routing and CSS for style sheet types, then type:
cd my-app
ng serve --open
Soon the application should be visible at http://localhost:4200/ in your default browser:
Now return to the command prompt and break out of ng serve by hitting Ctrl-C. We’ll use Angular CLI (the command-line interface) to create a simple Angular component and bind the data to an ordinary HTML table. At the prompt type:
ng generate component MyDataGrid
code .
ng serve
The first line creates our new component and the second opens Visual Studio Code to edit the files in the current directory. (You can use another editor if you prefer.) We don’t need the --open
parameter here; it’s assumed you still have the browser open.
Because ng serve
automatically rebuilds the app and refreshes the browser following each change saved in the editor, we’ll just keep editing and saving and see the results as we go.
Next, we’ll clean out some "cruft" from the app’s app.component.html page to make it easier to see the new component. So delete everything on that page from (and including) the line shown below (it’s line 329 in Angular version 8.2.14):
<div class="content" role="main">
And replace it all with this:
<app-my-data-grid></app-my-data-grid>
Here’s an excerpt from the end of the code showing the last few lines after the changes:
Once you save the changes, your browser should refresh as ng serve does a rebuild, and you should see the new component. Although a little underwhelming at the moment, we can at least now tell that it’s working:
Next, we’ll update the new component by adding a data source and linking this to a simple HTML table in our view, using conventional data binding and the Angular HTTPClientModule. First, edit the file app.module.ts to add the import reference shown below, then add the following in with the existing import statements:
import { HttpClientModule } from '@angular/common/http';
Now, add a reference to the module imports collection. Notice references already point to our new component. These were added automatically by Angular CLI when the component was created.
The final code should be:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { MyDataGridComponent } from './my-data-grid/my-data-grid.component';
import { HttpClientModule } from '@angular/common/http';
@NgModule({
declarations: [
AppComponent,
MyDataGridComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Next, go to the src/app/my-data-grid folder and open my-data-grid.component.ts. This is where we’ll add our data source. Add a reference to HttpClient alongside the other imports:
import { HttpClient } from '@angular/common/http';
And replace the default constructor:
constructor() { }
with the following:
data: any;
constructor(private http: HttpClient) {
this .http.get('https://data.gov.au/geoserver/ballarat-community-food-activities/wfs?request=GetFeature&typeName=ckan_70374622_81eb_4e84_ac43_587e4a4b8121&outputFormat=json')
.subscribe(data => {
this.data = data;
});
}
The final code should look like this:
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-my-data-grid',
templateUrl: './my-data-grid.component.html',
styleUrls: ['./my-data-grid.component.css']
})
export class MyDataGridComponent implements OnInit {
data: any;
constructor(private http: HttpClient) {
this .http.get('https://data.gov.au/geoserver/ballarat-community-food-activities/wfs?request=GetFeature&typeName=ckan_70374622_81eb_4e84_ac43_587e4a4b8121&outputFormat=json')
.subscribe(data => {
this.data = data;
});
}
ngOnInit() {
}
}
Save the file. Your browser should refresh, though with no visible changes yet. You can use the F12 browser debugger to look at the network traffic and should see the request for the JSON data just added:
Next, open the file my-data-grid.component.html to set up a JSON pipe to briefly analyze our data.
Add the following Angular debug code just after the existing line:
<pre>{{ data | json }}</pre>
Save the file and switch to your browser, where you’ll now see the structure of the JSON data:
Now, replace (or comment out) the Angular debug code shown below for our basic Angular 8 data-driven HTML table:
<p>my-data-grid works!</p>
<table>
<tr>
<th>Type</th>
<th>Name</th>
<th>Address</th>
</tr>
<tr *ngFor="let item of data.features">
<td>{{item.properties.type}}</td>
<td>{{item.properties.name}}</td>
<td>{{item.properties.address}}</td>
</tr>
</table>
Once you save your work, the browser will refresh and show the following:
For simple data with just a handful of rows, Angular 8 does make things easy. Unfortunately, when you start trying to add extra features, such as sorting, searching, grouping or filtering, your work quickly grows tedious.
We used a small, simple data sample for our project. For real-world situations, which generally involve more than a few rows (such as San Francisco’s Food Truck locations, 3000 rows of JSON data, we’d need to add pagination to make things intelligible. Apart from usability issues, too many rows of data would make our simple HTML tables and the associated Angular code (as we add sorting, filtering and so on) so large that the browser would slow to a crawl and might even crash.
Let’s see how easy it is to rescue our app from these issues as we switch from using basic HTML tables to Wijmo FlexGrid. Press Ctrl-C to return to your command shell and then type:
npm install @grapecity/wijmo.angular2.all
ng serve
Use npm to install the Wijmo library, then rerun ng serve
. We’ll edit app.module.ts again, this time to add references to the Wijmo library. Insert these lines near the HttpClientModule import added earlier:
import { WjGridModule } from '@grapecity/wijmo.angular2.grid';
import { WjGridFilterModule } from '@grapecity/wijmo.angular2.grid.filter';
Next, add the following lines to the module imports section. Take care to add commas between each entry:
WjGridModule,
WjGridFilterModule
Here’s the complete code for this step:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { MyDataGridComponent } from './my-data-grid/my-data-grid.component';
import { HttpClientModule } from '@angular/common/http';
import { WjGridModule } from '@grapecity/wijmo.angular2.grid';
import { WjGridFilterModule } from '@grapecity/wijmo.angular2.grid.filter';
@NgModule({
declarations: [
AppComponent,
MyDataGridComponent
],
imports: [
BrowserModule,
HttpClientModule,
WjGridModule,
WjGridFilterModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Let’s add a little CSS to the styles.css file to make our new data grid stand out. Notice that you can easily change the grid’s default fonts, and the width and height, as needed:
/* You can add global styles to this file, and also import other style files */
@import "@grapecity/wijmo.styles/themes/wijmo.theme.material.css";
body {
font-family: Lato, Arial, Helvetica;
}
.wj-flexgrid { /* limit the grid's width and height */
max-height: 300px;
max-width: 100%;
}
Now, we’re ready to update our component to use FlexGrid. First, in the file my-data-grid.component.ts, where we added our data source earlier, add the following to import the Wijmo library:
import * as WjCore from '@grapecity/wijmo';
Then update the code added earlier. We’re going to redefine our data type, since we’ll populate a Wijmo data collection. We’ll also simplify our databinding a little, and pick the features property from the data source before we pass it to the view.
Here’s the code that will update my-data-grid.component.ts:
data = new WjCore.CollectionView([], {
// add groupDescriptions here
});
constructor(private http: HttpClient) {
this .http.get('https://data.gov.au/geoserver/ballarat-community-food-activities/wfs?request=GetFeature&typeName=ckan_70374622_81eb_4e84_ac43_587e4a4b8121&outputFormat=json')
.subscribe(data => {
this.data.sourceCollection = data["features"];
});
}
The complete code for this step is shown here:
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import * as WjCore from '@grapecity/wijmo';
@Component({
selector: 'app-my-data-grid',
templateUrl: './my-data-grid.component.html',
styleUrls: ['./my-data-grid.component.css']
})
export class MyDataGridComponent implements OnInit {
data = new WjCore.CollectionView([], {
// add groupDescriptions here
});
constructor(private http: HttpClient) {
this .http.get('https://data.gov.au/geoserver/ballarat-community-food-activities/wfs?request=GetFeature&typeName=ckan_70374622_81eb_4e84_ac43_587e4a4b8121&outputFormat=json')
.subscribe(data => {
this.data.sourceCollection = data["features"];
});
}
ngOnInit() {
}
}
Next, edit the file my-data-grid.component.html to update the view:
<p>my-data-grid works!</p>
<!-- define the grid -->
<wj-flex-grid
[allowResizing]="'None'"
[alternatingRowStep]=0
[isReadOnly]="true"
[selectionMode]="'ListBox'"
[headersVisibility]="'Column'"
[itemsSource]="data">
<!-- define the columns -->
<wj-flex-grid-column [binding]="'properties.type'" [header]="'Type'" [width]="'*'">
</wj-flex-grid-column>
<wj-flex-grid-column [binding]="'properties.name'" [header]="'Name'" [width]="'*'">
</wj-flex-grid-column>
<wj-flex-grid-column [binding]="'properties.address'" [header]="'Address'" [width]="'*'">
</wj-flex-grid-column>
</wj-flex-grid>
Save your work, then check your browser and, voilà, you should see FlexGrid in action:
Note that you may see a watermark. This is removed once you buy and register your Wijmo tools.
Many core features are built into the product, including sorting. Try it—just click a column heading, then click again to sort in reverse order. And grouping is an easy alteration; just change the line in my-data-grid.component.ts reading this:
// add groupDescriptions here:
to this:
groupDescriptions: ['properties.type']
to indicate the grouping you need. Now save the file. Your browser will refresh to show grouping by your chosen column.
The screenshot shows this grouping in action, along with some groups "folded" away. Also visible is another out-of-the-box feature, row highlighting. FlexGrid has quite advanced single and multi-row and column selections, including shift-click and ctrl-click selectors.
It’s just as easy to highlight alternate rows—just flip the value in the HTML view, in file my-data-grid.component.html, from 0 to 1:
[alternatingRowStep]=1
Scratch-building cell editing can try anyone’s patience, but not with FlexGrid. Just flip the isReadOnly
attribute from true to false in <wj-flex-grid>
, then edit any cell just by pressing F2, as you would in Excel.
Once enabled, editing works across the whole grid. To prevent editing of, say, an ID column, just add the following to the attribute list of column(s) you want to make read only again:
[isReadOnly]="true"
By now it should be clear how simple and easy it is to convert your Angular application from using a basic data-bound HTML table to Wijmo FlexGrid instead. It’s equally easy to add paging and filtering, but though this really doesn’t require much code, space constraints prohibit detailing these features.
Follow this link to add paging (either client-side or server-side), and this link to add filtering.
The documentation here covers these and many other great features that Wijmo FlexGrid provides to enterprise developers of Angular apps.
Without much code, we’ve added an amazing interactive table to our application. It contains all the features users expect to see in a modern web app—and then some. Don’t forget that when you buy the Wijmo FlexGrid license, you also get use of the other great Wijmo components as well.
Unlike homegrown data grids, or other solutions, Wijmo FlexGrid doesn’t crash with large datasets either.
Have a look at the benchmarks to see just how well Wijmo FlexGrid performs.
Learn more about Wijmo/FlexGrid capabilities:
- Bernardo de Castilho shows how to create a customizable JavaScript DataGrid in minutes. Also linked are versions for Angular, React and Vue.
- Chris Bannon, Global Product Manager at GrapeCity, walks through implementing the new MultiRange selection mode now in FlexGrid version 5.