8000 With ivy, injecting a parent directive with the @host annotation fails in nested structures · Issue #36241 · angular/angular · GitHub
[go: up one dir, main page]

Skip to content
With ivy, injecting a parent directive with the @host annotation fails in nested structures #36241
Open
@martinbu

Description

@martinbu

🐞 bug report

Is this a regression?

Yes, in angular 8 this works fine. But after an update to angular 9 it stops working. If I opt-out ivy in the tsconfig.app.json ("enableIvy": false) it is working again.

Description

The problem occurs if a parent directive is injected with the @host annotation in nested structures. So the first injection works fine. But all injections in deeper nested structers fails and null is injected.

In the root component a ui property is defined which contains nested child elements.

@Component({
  selector: 'app-root',
  template: `
    <app-container [element]="ui"></app-container>
  `
})
export class AppComponent  {
  ui: ElementDef = {
    name: 'container1', child: {
      name: 'container2', child: {
        name: 'container3', child: {
          name: 'container4'
        }
      }
    }
  };
}

The elements are rendered by the container component. Each rendered element is embedded in a div with a directive "appContainerWrapper" attached.
The parent directive of a container is injected in the constructor with the @host annotation.

@Component({
  selector: 'app-container',
  template: `
    <div appContainerWrapper *ngIf="element">
      <p>Container: {{element.name}}</p>
      <app-container [element]="element.child"></app-container>
    </div>
  `
})
export class ContainerComponent implements OnInit {
  @Input() element: ElementDef;
  constructor(@Optional() @Host() private directive: ContainerWrapperDirective) {}
    [...]
  ngOnInit(): void {
    if (this.directive !== null) {
      this.directive.update(color);
    } else {
        // in nested containers this.directive is null if ivy is enabled :(
    }
  }
}

The directive should set the background color of the parent element if update is called from the child element.

@Directive({
    selector: '[appContainerWrapper]'
})
export class ContainerWrapperDirective {
    constructor(private containerWrapperRef: ElementRef, private renderer: Renderer2) {}

    update(color: string): void {
        const nativeElement = this.containerWrapperRef.nativeElement;
        this.renderer.setStyle(nativeElement, 'background-color', color);
    }
}

🔬 Minimal Reproduction

The problem cannot be reproduced in stackblitz. I therefor created a sample application on Github

The repository contains two branches:

  1. master: Angular 9 with ivy enabled --> the parent directive is only injected in the first container where a directive is available. In all further containers the injected directive is null. Therefor only one "background is set".
    grafik

  2. opt-out-ivy: same as the master branch but set "enableIvy" in tsconfig.app.json to false --> everything works as expected as with angular 8. In each container the parent directive is injected.
    grafik

🌍 Your Environment

Angular Version:


Angular CLI: 9.0.7
Node: 12.16.1
OS: win32 x64

Angular: 9.0.7
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.7
@angular-devkit/build-angular     0.900.7
@angular-devkit/build-optimizer   0.900.7
@angular-devkit/build-webpack     0.900.7
@angular-devkit/core              9.0.7
@angular-devkit/schematics        9.0.7
@ngtools/webpack                  9.0.7
@schematics/angular               9.0.7
@schematics/update                0.900.7
rxjs                              6.5.4
typescript                        3.7.5
webpack                           4.41.2

Metadata

Metadata

Labels

P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgentarea: coreIssues related to the framework runtimecore: difreq2: mediumstate: confirmedtype: bug/fix

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions

    0