diff --git a/packages/eslint-plugin/docs/rules/no-input-rename.md b/packages/eslint-plugin/docs/rules/no-input-rename.md
index 4bae04702..e14441ee7 100644
--- a/packages/eslint-plugin/docs/rules/no-input-rename.md
+++ b/packages/eslint-plugin/docs/rules/no-input-rename.md
@@ -655,6 +655,105 @@ class Test {}
#### ✅ Valid Code
+```ts
+@Component({
+ selector: 'qx-menuitem',
+ hostDirectives: [{
+ directive: CdkMenuItem,
+ inputs: ['cdkMenuItemDisabled: disabled'],
+ }]
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/no-input-rename": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### ✅ Valid Code
+
+```ts
+@Component({
+ selector: 'qx-menuitem',
+ 'hostDirectives': [{
+ directive: CdkMenuItem,
+ inputs: ['cdkMenuItemDisabled: disabled'],
+ }]
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/no-input-rename": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### ✅ Valid Code
+
+```ts
+@Component({
+ selector: 'qx-menuitem',
+ ['hostDirectives']: [{
+ directive: CdkMenuItem,
+ inputs: ['cdkMenuItemDisabled: disabled'],
+ }]
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/no-input-rename": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### ✅ Valid Code
+
```ts
@Component({})
class Test {
diff --git a/packages/eslint-plugin/src/rules/no-input-rename.ts b/packages/eslint-plugin/src/rules/no-input-rename.ts
index aa81e9a55..9431af5a5 100644
--- a/packages/eslint-plugin/src/rules/no-input-rename.ts
+++ b/packages/eslint-plugin/src/rules/no-input-rename.ts
@@ -139,6 +139,28 @@ export default createESLintRule({
[Selectors.INPUTS_METADATA_PROPERTY_LITERAL](
node: TSESTree.Literal | TSESTree.TemplateElement,
) {
+ const ancestorMaybeHostDirectiveAPI =
+ node.parent?.parent?.parent?.parent?.parent;
+ if (
+ ancestorMaybeHostDirectiveAPI &&
+ ASTUtils.isProperty(ancestorMaybeHostDirectiveAPI)
+ ) {
+ /**
+ * Angular v15 introduced the directive composition API: https://angular.io/guide/directive-composition-api
+ * Renaming host directive inputs using this API is not a bad practice and should not be reported
+ */
+ const hostDirectiveAPIPropertyName = 'hostDirectives';
+ if (
+ (ASTUtils.isLiteral(ancestorMaybeHostDirectiveAPI.key) &&
+ ancestorMaybeHostDirectiveAPI.key.value ===
+ hostDirectiveAPIPropertyName) ||
+ (TSESLintASTUtils.isIdentifier(ancestorMaybeHostDirectiveAPI.key) &&
+ ancestorMaybeHostDirectiveAPI.key.name ===
+ hostDirectiveAPIPropertyName)
+ ) {
+ return;
+ }
+ }
const [propertyName, aliasName] = withoutBracketsAndWhitespaces(
ASTUtils.getRawText(node),
).split(':');
diff --git a/packages/eslint-plugin/tests/rules/no-input-rename/cases.ts b/packages/eslint-plugin/tests/rules/no-input-rename/cases.ts
index 9cfbd6e53..05ac84021 100644
--- a/packages/eslint-plugin/tests/rules/no-input-rename/cases.ts
+++ b/packages/eslint-plugin/tests/rules/no-input-rename/cases.ts
@@ -50,6 +50,41 @@ export const valid = [
})
class Test {}
`,
+ /**
+ * Renaming inputs when using the directive composition API is not a bad practice
+ * https://angular.io/guide/directive-composition-api
+ * https://www.youtube.com/watch?v=EJJwyyjsRGs
+ */
+ `
+ @Component({
+ selector: 'qx-menuitem',
+ hostDirectives: [{
+ directive: CdkMenuItem,
+ inputs: ['cdkMenuItemDisabled: disabled'],
+ }]
+ })
+ class Test {}
+ `,
+ `
+ @Component({
+ selector: 'qx-menuitem',
+ 'hostDirectives': [{
+ directive: CdkMenuItem,
+ inputs: ['cdkMenuItemDisabled: disabled'],
+ }]
+ })
+ class Test {}
+ `,
+ `
+ @Component({
+ selector: 'qx-menuitem',
+ ['hostDirectives']: [{
+ directive: CdkMenuItem,
+ inputs: ['cdkMenuItemDisabled: disabled'],
+ }]
+ })
+ class Test {}
+ `,
`
@Component({})
class Test {