In version 26 of AG Grid we have added full typings to the Angular components
Applications with the strictTemplates
Angular compiler option enabled (default for v12+ apps) will fail to compile if grid properties are misconfigured via the components.
If you configure your grids solely through the
GridOptions
interface these changes will not impact you as you will already be using the correct types.
Prerequisite Setup
Before we can take advantage of the new AG Grid typings we need to ensure our application is set up appropriately.
Template Type Checking (Required)
To have Angular provide template validation you must enable the strictTemplates
flag under angularCompilerOptions
in your tsconfig.json
file. (This is only available if using Ivy).
{
"compilerOptions": { ... },
"angularCompilerOptions": {
"strictTemplates": true
}
}
// tsconfig.json
Without this flag, Angular ignores the specified types for @Inputs
and @Outputs
and provides no compile-time validation for you. It is strongly recommended to enable strictTemplates
for your application if possible. This is now enabled by default for new apps generated with the Angular CLI.
For more details see Template Type Checking.
Angular Language Service (Optional)
In the examples that follow we display screenshots that show code completion, navigation, hints and errors inside our template files. This is powered by the Angular Language Service. Instructions for setting it up for your editor of choice can be found in the Angular docs here.
The vast majority of the improved developer experience when using the new types comes from the Language Service.
Improved Developer Experience
To demonstrate the benefits of working with full typing we will add Input and Output properties to our grid and highlight the help we now get from the types.
Code Hints
Let us start by setting up conditional row classes as described in the Row Class Rules example. Previously you will have had to visit the documentation page to see the format of the object required as the Input had type any
.
However, with our new types, if you hover over the template property it reveals the type of this property as rowClassRules: RowClassRules | undefined;
Using code navigation (F12 for VS Code) we are now able to inspect the definition of RowClassRules
and quickly see the type information in our editor.
Note that we are now able to see the required format of the row class rules object without having to find the definition online. While we will still want to visit the docs for more information and examples, we are not forced to, just to see the name of properties. This should help speed up development by reducing the amount of context switching and documentation searching.
Real Time Error Reporting
The new typings will also enable you to quickly and confidently update code as if you provide the wrong type you will immediately be notified.
Previously you would have to let your app recompile and inspect the grid in your browser. Now you will be able to correct the error even before the app compiles.
Code Completion
There are improvements when we are working with @Output
events too as the $events
parameter is now strongly typed. For example, let's add an event handler for the gridsizeChanged
event.
If you hover over the gridSizeChanged
event in the template we see that the type of the event is GridSizeChangedEvent
.
We can then use this interface in our event handler and write code against the interface, taking advantage of code completion. No longer will you need to console.log($event)
in the dev tools to see which properties are available!
View the new Typings in Action
Developer Notes
Boolean Properties
The grid components have many boolean
properties and we have set up the components so that you are still able to set these using the shorthand notation. By this we mean enableCharts
is equivalent in behaviour to [enableCharts]=true
.
<ag-grid-angular
enableCharts
></ag-grid-angular>
This is made possible via Input Setter Coercion as without it, the attribute enableCharts
is interpreted as [enableCharts]="''"
. This would then fail the type check as the empty string
is not a boolean
type.
StrictNullChecks and the async pipe
When you enable strictTemplates
and the TypeScript flag strictNullChecks
you may find you have issues when setting some Inputs via Observables
with the async
pipe. The Angular documentation covers this in detail here.
For grid Inputs
rowData
andcolumnDefs
we explicitly accept null values which means the following is valid:. [rowData]= rowData$ | async
Boolean properties accept null as equivalent to
false
.
As an example, if you set up your rowHeight
as follows:
rowHeight$: Observable<number>;
And then pass this to the grid component.
<ag-grid-angular
[rowHeight]="rowHeight$ | async"
></ag-grid-angular>
If you have both strictTemplates
and the TypeScript flag strictNullChecks
enabled you will get a compilation error of:
Type 'null' is not assignable to type 'number | undefined'.
[rowHeight]="rowHeight$ | async"
This occurs because the async
pipe can return null
as a value when the Observable has not yet fired a value. With strict null checking null
cannot be assigned to the type of number | undefined
.
For AG Grid v25 and below this was not an error as the inputs all had type
any
and sonull
was silently accepted by the Input.
Potential Workarounds
The Angular documentation suggests potential workarounds depending on what is right for your application. However, in most cases, we would recommend providing a default value to use when the async
pipe returns null
.
In our example, we could provide a default row height of 50.
[rowHeight]="(rowHeight$ | async) || 50"
How are the Typings Applied?
You may be wondering why it has taken to v26 to have accurate types for the Angular components. To answer that it is important to understand that the Angular components are a hybrid of handwritten code and auto-generated properties.
At the time of writing, there are 282 Inputs and 72 Outputs on the grid component and a further 130 Inputs on the column component. As a result, we auto-generate the properties to avoid having to manually keep these in sync with the ever-changing GridOptions
and ColDef
interfaces.
In previous versions of the generation script, we had no way of knowing what the types were for each property. As a result, we could only add a generic Input and Output for each property.
@Input() public _PROPTERY_NAME_ : any = undefined;
@Output() public _PROPTERY_NAME_: EventEmitter<any> = new EventEmitter<any>();
However, we have now updated the script to use the Typescript parser to build a type lookup for all of the interface properties. This has enabled us to apply the real typing for each Input and Output by looking up the type for the given property name.
@Input() public _PROPTERY_NAME_ : _INPUT_TYPE_ = undefined;
@Output() public _PROPTERY_NAME_: EventEmitter<_OUTPUT_TYPE_> = new EventEmitter<_OUTPUT_TYPE_>();
By the same mechanism, we are also able to bring across any JSDoc comments and any deprecation annotations to the Angular components as soon as they are applied to the corresponding Typescript interface.
Future Proof Typings and Public Exports
The beauty of this approach is that the Angular types are future-proofed as they are updated with every internal build of AG Grid. Any changes to the GridOptions
interface are immediately reflected in the <ag-grid-angular>
This also ensures that new Interfaces are correctly exported from ag-grid-community
for use in your applications. This is because ag-grid-angular
uses the public exports from ag-grid-community
and so the internal build will now fail if the interfaces have not been exported. This benefits all Typescript users of AG Grid regardless of which framework they use.
Conclusion
We hope that you will find these new accurate typings for the Angular components <ag-grid-angular>
<ag-grid-column>
Learn more about AG Grid's Angular Support here.