Skip to content

ngOnInit is not respecting inheritance with AOT when base class is from an external librairy using barrel files #22825

Closed

Description

@instriker

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

When

  • I have a component base class (SimpleCoreComponent1) coming from an external npm library that implements ngOnInit
  • AND that class has been exported via barrel files (index.ts)
  • BUT that barrel file has been exported via implicit refererence to index.ts (export * from './components1'; instead of export * from './components1/index';)
  • AND I have an angular app with component (ForumsComponent) that extends SimpleCoreComponent1
  • BUT i didn't explicitly reimplement the ngOnInit in the ForumsComponent
  • AND i run the app with AOT enabled (ng server --aot)

Then

  • the ngOnInit of the base class is not invoked .

Expected behavior

Lifecycle hooks (ngOnInit, ngOnDestroy, etc) must be invoked even if the base class is defined in an external npm package using barrel files with index.ts not explicitly stated.

Minimal reproduction of the problem with instructions

STEPS TO REPRODUCE

Create the angular library

Note: Sample projet library source code available on github

  1. Setup library projet using yeoman
npm install -g yo@2.0.0
npm install -g generator-ngx-library@5.4.0
mkdir demolibraryforaot
cd demolibraryforaot
yo ngx-library
  1. Create this directory structure:
src
|- index.ts
|- Components1
   |- index.ts
   |- simple-core-component.ts
|- Components2
   |- index.ts
   |- simple-core-component.ts
   
  1. Write the following code:
// src/index.ts
export * from './components1';        // BUG: This export WON'T have the right .metadata.json exported:
export * from './components2/index';  // This export will have the right .metadata.json exported:

// src/Components1/index.ts
export * from './simple-core-component';

// src/Components1/simple-core-component.ts
import { OnInit } from '@angular/core';

export class SimpleCoreComponent1 implements OnInit {
    ngOnInit(): void {
        console.log('SimpleCoreComponent1.ngOnInit');
    }
}

// src/Components2/index.ts
export * from './simple-core-component';

// src/Components2/simple-core-component.ts
import { OnInit } from '@angular/core';

export class SimpleCoreComponent2 implements OnInit {
    ngOnInit(): void {
        console.log('SimpleCoreComponent2.ngOnInit');
    }
}
  1. Create a package
npm run start
# Ignore the code coverage error
cd dist
npm pack

Create the angular app

Note: Sample projet source code available on github

  1. Create an angular app beside the angular library
ng new angular-inh-aot-bug
  1. Install dependencies
cd angular-inh-aot-bug
npm install
  1. Install the npm package in the angular app
# Using locally built package:
npm install --save ../demolibraryforaot/dist/demolibraryforaot-0.0.1.tgz
  1. Create a component in the angular app
cd src/app
ng generate component ForumsComponent
  1. Edit ForumsComponent to extends SimpleCoreComponent1
import { Component } from '@angular/core';
import { SimpleCoreComponent1 } from 'demolibraryforaot';

@Component({
  selector: 'app-forums',
  templateUrl: './forums.component.html',
  styleUrls: ['./forums.component.css']
})
export class ForumsComponentWithoutIndex extends SimpleCoreComponent1 {
}
  1. Add the ForumsComponent to the AppComponent.html:
<app-forums></app-forums>
  1. Start with AOT:
ng serve --aot 
  1. Open browser and see the base class ngOnInit is not invoked (no logs in the console)
    Open http://localhost:4200 in chrome

Now extends SimpleCoreComponent2 instead of SimpleCoreComponent1

Look at the console log: you'll see the ngOnInit is now invoked. The reason seems to be that the .metadata.json of the library is OK when we have the /index in the export of the barrel file.

What is the motivation / use case for changing the behavior?

We have a lot of angular projects expected to start in the near future. We want to be able to extract some of the good recipes teams develops in a common librairy to help cross-project collaboration.

That bug is 'nasty', as it's easy to do this kind of error, and not obvious for people investigating that bug why their code is not invoked.

Environment


Angular version: 5.2.8

Browser:
- [x] Chrome (desktop) version 64.0.3282.186 
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
 
For Tooling issues:
- Node version: 5.6.0
- Platform:  Windows

Others:

Activity

  1. added this to the needsTriage milestone on Mar 16, 2018
  2. modified the milestones: needsTriage, Backlog on Mar 29, 2018
  3. DcsMarcRemolt commented on Jun 28, 2018

    @DcsMarcRemolt

    The same bug is still present in ng6, the external lib is even compiled with the new cli library feature in my case. Also it is not limited to ngOnInit, at least ngOnDestroy is also affected as I use this one extensively.

    I work around this by adding an empty base class into every project extending the base class from the lib. There I define the ngOnXXX with explicitly calling super.ngOnXXX().

    By using only the base class from the project, the callbacks fire again. Not perfect but better than not using inheritance at all.

  4. JoostK commented on Mar 15, 2020

    @JoostK
    Member

    This is no longer an issue in Ivy! I just tested your repro in Angular 9.0 and it still fails in ViewEngine, but works in Ivy.

  5. angular-automatic-lock-bot commented on Apr 15, 2020

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  6. locked and limited conversation to collaborators on Apr 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions