5 ESLint rules to enforce modern Angular features

Wojciech Trawiński
JavaScript everyday
4 min readJun 24, 2024
Photo by Renato Pozzi on Unsplash

Angular has recently introduced many new features that are worth exploring. The initial step involves familiarizing yourself with these additions before incorporating them into your projects.

However, memorizing all these features can be challenging, especially when working in a large codebase with numerous contributors. Therefore, it’s beneficial to use a reliable tool like ESLint, which can enforce the use of these new features.

In this blog post, I will discuss five ESLint rules from the angular-eslint package that you should consider enabling in your Angular application.

self-closing components tags

Let’s start with something simple yet useful. Although it’s not a game-changer, it still improves readability and enhances the developer experience (DX).

The following rule enforces the pattern:

// @ts-check
const eslint = require("@eslint/js");
const tseslint = require("typescript-eslint");
const angular = require("angular-eslint");

module.exports = tseslint.config(
{
files: ["**/*.html"],
extends: [
...angular.configs.templateRecommended,
...angular.configs.templateAccessibility,
],
rules: {
"@angular-eslint/template/prefer-self-closing-tags": ["warn|error"],
},
},
...
);

Moreover, the rule supports autofix. This allows you to easily switch to self-closing tags by running ng lint --fix.

standalone architecture

Many developers are already familiar with a world without NgModules. However, you can still enforce it using the following rule:

// @ts-check
const eslint = require("@eslint/js");
const tseslint = require("typescript-eslint");
const angular = require("angular-eslint");

module.exports = tseslint.config(
{
files: ["**/*.ts"],
extends: [
eslint.configs.recommended,
...tseslint.configs.recommended,
...tseslint.configs.stylistic,
...angular.configs.tsRecommended,
],
processor: angular.processInlineTemplates,
rules: {
"@angular-eslint/prefer-standalone": ["warn|error"],
},
},
...
);

It’s better to be safe than sorry.

Although the rule supports autofix, switching to standalone mode often requires extra work.

You can set the defaults in the angular.json (nx.json) file. However, there’s nothing stopping you from avoiding the Angular CLI, so the ESLint rule serves as a secondary defense line.

optimized images

Angular introduced the NgOptimizedImage directive to address common issues with image assets. This directive focuses on improving Core Web Vitals metrics such as Largest Contentful Paint (LCP) and Cumulative Layout Shift (CLS), while also enforcing overall best practices. Without a doubt, using the directive is a better choice than the native src attribute.

The following ESLint rule covers this:

// @ts-check
const eslint = require("@eslint/js");
const tseslint = require("typescript-eslint");
const angular = require("angular-eslint");

module.exports = tseslint.config(
{
files: ["**/*.html"],
extends: [
...angular.configs.templateRecommended,
...angular.configs.templateAccessibility,
],
rules: {
"@angular-eslint/template/prefer-ngsrc": ["warn|error"],
},
},
...
);

built-in control flow syntax

The well-known NgFor structural directive is no longer recommended for iterating over a collection of items in a component’s template. The built-in control flow syntax, which includes the for loop, is now preferred. This alternative not only offers a more intuitive syntax, but it also leads to significant performance improvements.

The following rule enables the enforcement of the new solution:

// @ts-check
const eslint = require("@eslint/js");
const tseslint = require("typescript-eslint");
const angular = require("angular-eslint");

module.exports = tseslint.config(
{
files: ["**/*.html"],
extends: [
...angular.configs.templateRecommended,
...angular.configs.templateAccessibility,
],
rules: {
"@angular-eslint/template/prefer-control-flow": ["warn|error"],
},
},
...
);

zoneless change detection

Angular 18 introduces experimental support for zoneless change detection. As noted in my previous blog post, if your code is compatible with the OnPush change detection strategy, it is essentially prepared for this upcoming zoneless future.

Hence, it’s beneficial to apply the OnPush change detection strategy using the following rule:

// @ts-check
const eslint = require("@eslint/js");
const tseslint = require("typescript-eslint");
const angular = require("angular-eslint");

module.exports = tseslint.config(
{
files: ["**/*.ts"],
extends: [
eslint.configs.recommended,
...tseslint.configs.recommended,
...tseslint.configs.stylistic,
...angular.configs.tsRecommended,
],
processor: angular.processInlineTemplates,
rules: {
"@angular-eslint/prefer-on-push-component-change-detection": ["warn|error"],
},
},
...
);

Furthermore, you can set it as the default in the angular.json (nx.json) file.

In conclusion, the five ESLint rules from the angular-eslint package can significantly improve the development of Angular applications. They not only enforce best practices but also aid in maintaining code consistency, particularly in large codebases with numerous contributors.

I hope you liked my blog post, thanks for reading! 🙂

--

--