Skip to content

@ngrx/eslint-plugin rules linting Angular HTML templates #5088

@ivayloc

Description

@ivayloc

Which @ngrx/* package(s) are the source of the bug?

eslint-plugin

Minimal reproduction of the bug/regression with instructions

After installing @ngrx/eslint-plugin@21.0.1 and importing the plugin rules in a flat config (eslint.config.mjs), linting fails with the same runtime error for every NgRx rule:

Error while loading rule '@ngrx/avoid-combining-component-store-selectors': Cannot read properties of undefined (reading 'filter')

From debugging, it looks like the NgRx rules are being executed for Angular component templates (*.html).
The linting fails for my libraries. If I add an override for **/*.html and disable the imported NgRx rules there, linting works fine.

Main config

import nx from '@nx/eslint-plugin';
import ngrx from '@ngrx/eslint-plugin/v9';

export default [
  ...nx.configs['flat/base'],
  ...nx.configs['flat/typescript'],
  ...nx.configs['flat/javascript'],
  ...ngrx.configs['all'],
  {
    ignores: ['**/dist', '**/out-tsc', 'libs/swagger-generator/**'],
  },
  {
    files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
    rules: {
      '@nx/enforce-module-boundaries': [
        'error',
        {
          enforceBuildableLibDependency: true,
          allow: ['^.*/eslint(\\.base)?\\.config\\.[cm]?[jt]s$'],
          depConstraints: [
            {
              sourceTag: '*',
              onlyDependOnLibsWithTags: ['*'],
            },
          ],
        },
      ],
    },
  },
  {
    files: ['**/*.ts'],
    // Override or add rules here
    rules: {
      '@ngrx/avoid-combining-component-store-selectors': 'off',
      '@ngrx/avoid-mapping-component-store-selectors': 'off',
      '@ngrx/updater-explicit-return-type': 'off',
      '@ngrx/avoid-combining-selectors': 'warn',
      '@ngrx/avoid-dispatching-multiple-actions-sequentially': 'warn',
      '@ngrx/avoid-duplicate-actions-in-reducer': 'warn',
      '@ngrx/avoid-mapping-selectors': 'warn',
      '@ngrx/good-action-hygiene': 'warn',
      '@ngrx/no-multiple-global-stores': 'warn',
      '@ngrx/no-reducer-in-key-names': 'warn',
      '@ngrx/no-store-subscription': 'warn',
      '@ngrx/prefer-action-creator-in-dispatch': 'warn',
      '@ngrx/prefer-action-creator-in-of-type': 'warn',
      '@ngrx/prefer-action-creator': 'warn',
      '@ngrx/prefer-concat-latest-from': 'warn',
      '@ngrx/prefer-effect-callback-in-block-statement': 'off',
      '@ngrx/prefer-inline-action-props': 'warn',
      '@ngrx/prefer-one-generic-in-create-for-feature-selector': 'warn',
      '@ngrx/prefer-selector-in-select': 'warn',
      '@ngrx/prefix-selectors-with-select': 'error',
      '@ngrx/select-style': 'warn',
      '@ngrx/use-consistent-global-store-name': 'warn',
      '@ngrx/use-effects-lifecycle-interface': 'warn',
      '@ngrx/no-dispatch-in-effects': 'warn',
    },
  }
];

Library config

import nx from '@nx/eslint-plugin';
import baseConfig from '../../eslint.config.mjs';

export default [
  ...baseConfig,
  {
    files: ['**/*.json'],
    rules: {
      '@nx/dependency-checks': [
        'error',
        {
          ignoredFiles: ['{projectRoot}/eslint.config.{js,cjs,mjs,ts,cts,mts}'],
        },
      ],
    },
    languageOptions: {
      parser: await import('jsonc-eslint-parser'),
    },
  },
  ...nx.configs['flat/angular'],
  ...nx.configs['flat/angular-template'],
  {
    files: ['**/*.ts'],
    rules: {
      '@angular-eslint/directive-selector': [
        'error',
        {
          type: 'attribute',
          prefix: ['app', 'ui'],
          style: 'camelCase',
        },
      ],
      '@angular-eslint/component-selector': [
        'error',
        {
          type: 'element',
          prefix: ['app', 'ui'],
          style: 'kebab-case',
        },
      ],
    },
  },
  {
    files: ['**/*.html'],
    // Override or add rules here
    rules: {
      '@angular-eslint/template/click-events-have-key-events': 'off',
      '@angular-eslint/template/interactive-supports-focus': 'off',
      '@angular-eslint/template/alt-text': 'off',
      '@angular-eslint/template/label-has-associated-control': 'off',
      '@angular-eslint/template/elements-content': 'off',
      // NGRX
      '@ngrx/avoid-combining-component-store-selectors': 'off',
      '@ngrx/avoid-mapping-component-store-selectors': 'off',
      '@ngrx/require-super-ondestroy': 'off',
      '@ngrx/updater-explicit-return-type': 'off',
      '@ngrx/no-dispatch-in-effects': 'off',
      '@ngrx/no-effects-in-providers': 'off',
      '@ngrx/prefer-action-creator-in-of-type': 'off',
      '@ngrx/prefer-effect-callback-in-block-statement': 'off',
      '@ngrx/use-effects-lifecycle-interface': 'off',
      '@ngrx/prefer-concat-latest-from': 'off',
      '@ngrx/enforce-type-call': 'off',
      '@ngrx/prefer-protected-state': 'off',
      '@ngrx/signal-store-feature-should-use-generic-type': 'off',
      '@ngrx/avoid-combining-selectors': 'off',
      '@ngrx/avoid-dispatching-multiple-actions-sequentially': 'off',
      '@ngrx/avoid-duplicate-actions-in-reducer': 'off',
      '@ngrx/avoid-mapping-selectors': 'off',
      '@ngrx/good-action-hygiene': 'off',
      '@ngrx/no-multiple-global-stores': 'off',
      '@ngrx/no-reducer-in-key-names': 'off',
      '@ngrx/no-store-subscription': 'off',
      '@ngrx/no-typed-global-store': 'off',
      '@ngrx/on-function-explicit-return-type': 'off',
      '@ngrx/prefer-action-creator-in-dispatch': 'off',
      '@ngrx/prefer-action-creator': 'off',
      '@ngrx/prefer-inline-action-props': 'off',
      '@ngrx/prefer-one-generic-in-create-for-feature-selector': 'off',
      '@ngrx/prefer-selector-in-select': 'off',
      '@ngrx/prefix-selectors-with-select': 'off',
      '@ngrx/select-style': 'off',
      '@ngrx/use-consistent-global-store-name': 'off',
    },
  },
  {
    files: ['**/*.effects.ts'],
    // Override or add rules here
    rules: {},
  },
];

Expected behavior

Eslint rules should not be applied to *.html files when used with files: ["**/*.ts"]

Versions of NgRx, Angular, Node, affected browser(s) and operating system(s)

NgRx: 20.0.1
@ngrx/eslint-plugin": "21.0.1",
Angular: 20.3.3
Node: 24.9.0
OS: macOS Tahoe 26.2 (25C56)

Other information

No response

I would be willing to submit a PR to fix this issue

  • Yes
  • No

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions