Skip to content
rdlabo.devdocs

Check your Kit integration with ESLint

Keep modal launchers, async action handlers, and form errors consistent as your Ionic Angular app grows. @rdlabo/eslint-plugin-rules checks the call patterns that work with @rdlabo/ionic-angular-kit.

Enable the checks you use

In an Ionic Angular 9 app with Angular / Angular ESLint 21–22 configured:

npm install --save-dev @rdlabo/eslint-plugin-rules@22

Merge these entries into eslint.config.mjs, retaining your existing checks. They enable four focused rules; choose the ones that match the Kit features in your app.

import tseslint from 'typescript-eslint';
import angular from 'angular-eslint';
import rdlabo from '@rdlabo/eslint-plugin-rules';

export default tseslint.config(
  {
    files: ['**/*.ts'],
    languageOptions: { parser: tseslint.parser },
    processor: angular.processInlineTemplates,
    plugins: { '@rdlabo/rules': rdlabo },
    rules: {
      '@rdlabo/rules/deny-overlay-create': 'error',
      '@rdlabo/rules/prefer-modal-launcher': 'error',
    },
  },
  {
    files: ['**/*.html'],
    languageOptions: { parser: angular.templateParser },
    plugins: { '@rdlabo/rules': rdlabo },
    rules: {
      '@rdlabo/rules/prefer-disable-handler': 'error',
      '@rdlabo/rules/require-ion-error-text': 'error',
    },
  },
);

These rules are also included in rdlabo.configs.recommended.

Keep modal creation in a launcher

deny-overlay-create reports .create() calls on ModalController and PopoverController. prefer-modal-launcher checks that presentModal calls live in launch* functions.

With overlay and DetailPage from your overlay setup, this is reported:

export const openDetail = () => overlay.presentModal(DetailPage);

Use a launcher:

export const launchDetail = () => overlay.presentModal(DetailPage);

Keep async actions wrapped

prefer-disable-handler reports an unwrapped action:

<ion-button type="button" (click)="vm.refresh()">Refresh</ion-button>

Expose the Kit's disableHandler helper on your component or ViewModel, then pass the event and async work:

import { disableHandler } from '@rdlabo/ionic-angular-kit';

// Inside the component or ViewModel:
readonly disableHandler = disableHandler;
<ion-button type="button" (click)="vm.disableHandler($event, vm.refresh())">Refresh</ion-button>

The rule checks the wrapper call, not the async work's behavior. Keep submit actions on the form's (submit) with ion-button type="submit".

Match the Signal Forms adapter

By default, require-ion-error-text requires an error text source on Ionic controls with [formField].

For Angular 22 apps using Kit Signal Forms, import FormField and KitIonicFormField in each relevant component and install provideKitIonicSignalForms(). Then override this entry in the HTML config's rules:

'@rdlabo/rules/require-ion-error-text': [
  'error',
  { formFieldProvidesErrorText: true },
],

This option declares that the adapter supplies error text; ESLint does not verify the adapter's imports or providers.

Add ViewModel policy when you use it

If your app uses a ViewModelStore architecture, add require-viewmodel and no-component-writable-signal. Configure them around your app's ViewModel base; ViewModelStore is not a Kit export.

Run it in CI

After installing dependencies, run locally and in CI:

npx eslint 'src/**/*.{ts,html}' --max-warnings 0

Adjust the source path for your app. See ESLint configuration for the complete recommended policy and rule options for other conventions.