diff --git a/packages/eslint-plugin/docs/rules/no-inputs-metadata-property.md b/packages/eslint-plugin/docs/rules/no-inputs-metadata-property.md
index 7d86b54a9..69759ff75 100644
--- a/packages/eslint-plugin/docs/rules/no-inputs-metadata-property.md
+++ b/packages/eslint-plugin/docs/rules/no-inputs-metadata-property.md
@@ -489,6 +489,105 @@ class Test {}
class Test {}
```
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/no-inputs-metadata-property": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### ✅ Valid Code
+
+```ts
+@Component({
+ selector: 'qx-menuitem',
+ hostDirectives: [{
+ directive: CdkMenuItem,
+ inputs: ['cdkMenuItemDisabled: disabled'],
+ }]
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/no-inputs-metadata-property": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### ✅ Valid Code
+
+```ts
+@Component({
+ selector: 'qx-menuitem',
+ 'hostDirectives': [{
+ directive: CdkMenuItem,
+ inputs: ['cdkMenuItemDisabled: disabled'],
+ }]
+})
+class Test {}
+```
+
+
+
+---
+
+
+
+#### Default Config
+
+```json
+{
+ "rules": {
+ "@angular-eslint/no-inputs-metadata-property": [
+ "error"
+ ]
+ }
+}
+```
+
+
+
+#### ✅ Valid Code
+
+```ts
+@Component({
+ selector: 'qx-menuitem',
+ ['hostDirectives']: [{
+ directive: CdkMenuItem,
+ inputs: ['cdkMenuItemDisabled: disabled'],
+ }]
+})
+class Test {}
+```
+
diff --git a/packages/eslint-plugin/src/rules/no-inputs-metadata-property.ts b/packages/eslint-plugin/src/rules/no-inputs-metadata-property.ts
index e48624cb1..2a91c0eaa 100644
--- a/packages/eslint-plugin/src/rules/no-inputs-metadata-property.ts
+++ b/packages/eslint-plugin/src/rules/no-inputs-metadata-property.ts
@@ -1,5 +1,6 @@
-import { Selectors } from '@angular-eslint/utils';
+import { ASTUtils, Selectors } from '@angular-eslint/utils';
import type { TSESTree } from '@typescript-eslint/utils';
+import { ASTUtils as TSESLintASTUtils } from '@typescript-eslint/utils';
import { createESLintRule } from '../utils/create-eslint-rule';
type Options = [];
@@ -29,6 +30,30 @@ export default createESLintRule({
} ${Selectors.metadataProperty(METADATA_PROPERTY_NAME)}`](
node: TSESTree.Property,
) {
+ /**
+ * Angular v15 introduced the directive composition API: https://angular.io/guide/directive-composition-api
+ * Using host directive inputs using this API is not a bad practice and should not be reported
+ */
+ const ancestorMayBeHostDirectiveAPI = node.parent?.parent?.parent;
+
+ if (
+ ancestorMayBeHostDirectiveAPI &&
+ ASTUtils.isProperty(ancestorMayBeHostDirectiveAPI)
+ ) {
+ const hostDirectiveAPIPropertyName = 'hostDirectives';
+
+ if (
+ (ASTUtils.isLiteral(ancestorMayBeHostDirectiveAPI.key) &&
+ ancestorMayBeHostDirectiveAPI.key.value ===
+ hostDirectiveAPIPropertyName) ||
+ (TSESLintASTUtils.isIdentifier(ancestorMayBeHostDirectiveAPI.key) &&
+ ancestorMayBeHostDirectiveAPI.key.name ===
+ hostDirectiveAPIPropertyName)
+ ) {
+ return;
+ }
+ }
+
context.report({
node,
messageId: 'noInputsMetadataProperty',
diff --git a/packages/eslint-plugin/tests/rules/no-inputs-metadata-property/cases.ts b/packages/eslint-plugin/tests/rules/no-inputs-metadata-property/cases.ts
index 1ce7075ab..2edb3f9b3 100644
--- a/packages/eslint-plugin/tests/rules/no-inputs-metadata-property/cases.ts
+++ b/packages/eslint-plugin/tests/rules/no-inputs-metadata-property/cases.ts
@@ -45,6 +45,41 @@ export const valid = [
})
class Test {}
`,
+ /**
+ * Using 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 {}
+ `,
];
export const invalid = [