Skip to content

NG0311: Input/output object literal mapping to array breaks host directive validation #54096

@cyr-x

Description

@cyr-x

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

compiler

Is this a regression?

No

Description

When creating a host directive which uses the input/output mapping feature the compiler transforms those mapping into an array which breaks the host directive validation in @angular/core.

Steps to reproduce:

  1. Create a library which contains a directive which defines a host directive and maps it's inputs:
@Directive({
  standalone: true,
  selector: '[appTest]',
  hostDirectives: [
    {
      directive: HostDirective,
      inputs: ['hostInput:testInput'],
    },
  ],
})
export class TestDirective {}
  1. Build the library with partial compilation mode
    The compiler will transform the host directive metadata to:
hostDirectives: [{ directive: i1$1.HostDirective, inputs: ["hostInput", "odxMenu"] }]

export function createHostDirectivesMappingArray(mapping: Record<string, string>):

3. Use the library in another project, the core package will report the NG0311 error.

This is because in @angular/core a validation check fails in when the dev mode is active:

if (!bindings.hasOwnProperty(publicName)) {

Please provide a link to a minimal reproduction of the bug

No response

Please provide the exception or error you saw

NG0311: Directive _a does not have an input with a public name of menu.

at validateMappings (../../../node_modules/@angular/core/fesm2022/core.mjs:14715:23)
at validateHostDirective (../../../node_modules/@angular/core/fesm2022/core.mjs:14700:5)
at Object.findHostDirectiveDefs (../../../node_modules/@angular/core/fesm2022/core.mjs:14616:17)
at findDirectiveDefMatches (../../../node_modules/@angular/core/fesm2022/core.mjs:12727:21)
at resolveDirectives (../../../node_modules/@angular/core/fesm2022/core.mjs:12492:29)

Please provide the environment you discovered this bug in (run ng version)

Angular CLI: 16.2.12
Node: 18.18.0
Package Manager: npm 10.3.0
OS: linux x64

Angular: 16.2.12
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router, service-worker

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1602.12
@angular-devkit/build-angular   16.2.12
@angular-devkit/core            16.2.12
@angular-devkit/schematics      16.2.12
@angular/cdk                    16.2.13
@schematics/angular             16.2.11
ng-packagr                      16.2.3
rxjs                            7.8.1
typescript                      5.1.6
webpack                         5.89.0
zone.js                         0.13.3

Anything else?

A possible solution might be to merge the input alias again:

function createHostDirectivesMappingArray(mapping) {
    const elements = [];
    for (const publicName in mapping) {
        if (mapping.hasOwnProperty(publicName)) {
          const mappedPublicName = mapping[publicName];
          const literalName = mappedPublicName === publicName ? publicName : `${publicName}:${mappedPublicName}`;
          elements.push(literal(literalName));
        }
    }
    return elements.length > 0 ? literalArr(elements) : null;
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions