@angular-eslint/eslint-plugin
Version:
ESLint plugin for Angular applications, following https://angular.dev/style-guide
72 lines (71 loc) • 3.79 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RULE_DOCS_EXTENSION = exports.RULE_NAME = void 0;
const utils_1 = require("@angular-eslint/utils");
const create_eslint_rule_1 = require("../utils/create-eslint-rule");
exports.RULE_NAME = 'prefer-signal-model';
exports.default = (0, create_eslint_rule_1.createESLintRule)({
name: exports.RULE_NAME,
meta: {
type: 'suggestion',
docs: {
description: 'Use `model` instead of `input` and `output` for two-way bindings',
},
fixable: 'code',
schema: [],
messages: {
preferSignalModel: 'Use `model` for two-way bindings instead of `input()` and `output()`',
},
},
defaultOptions: [],
create(context) {
const inputs = new Map();
const outputs = new Map();
return {
"PropertyDefinition > CallExpression[callee.name='input']"(node) {
const propertyDef = node.parent;
const propertyName = utils_1.ASTUtils.getPropertyDefinitionName(propertyDef);
inputs.set(propertyName, propertyDef);
},
"PropertyDefinition > CallExpression[callee.name='output']"(node) {
const propertyDef = node.parent;
const propertyName = utils_1.ASTUtils.getPropertyDefinitionName(propertyDef);
outputs.set(propertyName, propertyDef);
},
'ClassDeclaration:exit'() {
for (const [inputName, inputProperty] of inputs) {
const outputName = `${inputName}Change`;
const outputProperty = outputs.get(outputName);
if (outputProperty) {
// Report on the input property
context.report({
node: inputProperty,
messageId: 'preferSignalModel',
fix: (fixer) => {
const sourceCode = context.sourceCode;
const inputText = sourceCode.getText(inputProperty);
const fixedInputText = inputText.replace(/\binput\b/, 'model');
return [
utils_1.RuleFixes.getImportAddFix({
fixer,
importName: 'model',
moduleName: '@angular/core',
node: inputProperty,
}),
fixer.replaceText(inputProperty, fixedInputText),
fixer.remove(outputProperty),
].filter(utils_1.isNotNullOrUndefined);
},
});
}
}
// Clear the maps for the next class
inputs.clear();
outputs.clear();
},
};
},
});
exports.RULE_DOCS_EXTENSION = {
rationale: "The model() function is Angular's modern API for two-way bindings, combining both input and output into a single signal. When you have an input property paired with an output property that follows the naming pattern of `propertyChange` (e.g., `enabled` input with `enabledChange` output), this is the traditional pattern for two-way binding. The model() function provides a cleaner, more concise way to express this pattern with better type safety and integration with Angular's signal ecosystem. It eliminates the boilerplate of managing separate input and output properties while maintaining the same two-way binding functionality.",
};