Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angular dependency injection not working #15185

Closed
massi08 opened this issue Jun 9, 2021 · 13 comments
Closed

Angular dependency injection not working #15185

massi08 opened this issue Jun 9, 2021 · 13 comments

Comments

@massi08
Copy link

massi08 commented Jun 9, 2021

Describe the bug
Angular dependency injection doesn't seem to work right with Angular 9.

To Reproduce
Simply import ChangeDetectorRef in component constructor

  constructor(private cdr: ChangeDetectorRef) {
  }

Component story:

import {RadioComponent, RadioGroupComponent} from '@engie-group/fluid-design-system-angular';
import {Meta, moduleMetadata, Story} from '@storybook/angular';

export default {
  title: 'Radio/Radio Group',
  component: RadioGroupComponent,
  argTypes: {
    value: {
      description: 'Radio group selected value',
      control: {
        type: null,
      },
    },
    selected: {
      description: 'Radio group selected radio component',
    },
    name: {
      description: 'Radio group name, this will force all the children radios to have this name',
    },
    isDisabled: {
      description: 'Whether the radio group is disabled or not, this will force all the children radios be disabled or not depending on this value',
      control: {
        type: 'boolean'
      },
    },
    orientation: {
      description: 'Whether the radio group should be displayed in column or row',
      control: {
        type: 'radio',
      },
      table: {
        defaultValue: {
          summary: 'column'
        }
      }
    },
    required: {
      description: 'Whether radio is required or not',
      control: {
        type: null,
      },
    },
    valueChange: {
      description: 'Output that emits checked value on change only',
      control: {
        type: null,
      },
    },
  },
  decorators: [
    moduleMetadata({
      declarations: [RadioGroupComponent, RadioComponent],
    }),
  ],
  parameters: {
    docs: {
      description: {
        component: '`<nj-radio-group>` is compatible with `@angular/forms` and supports both `FormsModule` and `ReactiveFormsModule`'
      }
    },
  }
} as Meta;

export const RadioGroup: Story = (args) => ({
  props: {
    orientation: args.orientation,
    value: args.value,
    isDisabled: args.isDisabled,
  },
  template: `
    <nj-radio-group [value]="${args.value}" [isDisabled]="${args.isDisabled}" [orientation]="${args.orientation}">
     <nj-radio value="option1">Option 1</nj-radio>
     <nj-radio value="option2" [isDisabled]="true">Option 2</nj-radio>
     <nj-radio value="option3">Option 3</nj-radio>
     <nj-radio value="option4">Option 4</nj-radio>
    </nj-radio-group>
    `
});

RadioGroup.args = {
  orientation: 'column',
  isDisabled: null,
  value: null,
};

Browser Error:

ERROR NullInjectorError: StaticInjectorError(ElementsModule)[RadioComponent -> ChangeDetectorRef]: 
  StaticInjectorError(Platform: core)[RadioComponent -> ChangeDetectorRef]: 
    NullInjectorError: No provider for ChangeDetectorRef!
    at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (core.js:937)
    at resolveToken (core.js:12202)
    at tryResolveToken (core.js:12146)
    at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:12040)
    at resolveToken (core.js:12202)
    at tryResolveToken (core.js:12146)
    at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:12040)
    at resolveNgModuleDep (core.js:21927)
    at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (core.js:22528)
    at resolveDep (core.js:22907)

Unhandled Promise rejection: StaticInjectorError(ElementsModule)[RadioComponent -> ChangeDetectorRef]: 
  StaticInjectorError(Platform: core)[RadioComponent -> ChangeDetectorRef]: 
    NullInjectorError: No provider for ChangeDetectorRef! ; Zone: <root> ; Task: Promise.then ; Value: NullInjectorError: StaticInjectorError(ElementsModule)[RadioComponent -> ChangeDetectorRef]: 
  StaticInjectorError(Platform: core)[RadioComponent -> ChangeDetectorRef]: 
    NullInjectorError: No provider for ChangeDetectorRef!
    at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (core.js:937)
    at resolveToken (core.js:12202)
    at tryResolveToken (core.js:12146)
    at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:12040)
    at resolveToken (core.js:12202)
    at tryResolveToken (core.js:12146)
    at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:12040)
    at resolveNgModuleDep (core.js:21927)
    at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (core.js:22528)
    at resolveDep (core.js:22907) NullInjectorError: StaticInjectorError(ElementsModule)[RadioComponent -> ChangeDetectorRef]: 
  StaticInjectorError(Platform: core)[RadioComponent -> ChangeDetectorRef]: 
    NullInjectorError: No provider for ChangeDetectorRef!
    at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (http://localhost:6006/vendors~main.iframe.bundle.js:100945:25)
    at resolveToken (http://localhost:6006/vendors~main.iframe.bundle.js:112210:24)
    at tryResolveToken (http://localhost:6006/vendors~main.iframe.bundle.js:112154:16)
    at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (http://localhost:6006/vendors~main.iframe.bundle.js:112048:20)
    at resolveToken (http://localhost:6006/vendors~main.iframe.bundle.js:112210:24)
    at tryResolveToken (http://localhost:6006/vendors~main.iframe.bundle.js:112154:16)
    at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (http://localhost:6006/vendors~main.iframe.bundle.js:112048:20)
    at resolveNgModuleDep (http://localhost:6006/vendors~main.iframe.bundle.js:121935:29)
    at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (http://localhost:6006/vendors~main.iframe.bundle.js:122536:16)
    at resolveDep (http://localhost:6006/vendors~main.iframe.bundle.js:122915:45)
api.onUnhandledError @ zone.js:690
handleUnhandledRejection @ zone.js:713
_loop_1 @ zone.js:704
api.microtaskDrainDone @ zone.js:708
drainMicroTaskQueue @ zone.js:608
Promise.then (async)
scheduleMicroTask @ zone.js:584
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:410
push../node_modules/zone.js/dist/zone.js.Zone.scheduleTask @ zone.js:231
push../node_modules/zone.js/dist/zone.js.Zone.scheduleMicroTask @ zone.js:251
scheduleResolveOrReject @ zone.js:881
resolvePromise @ zone.js:819
(anonymous) @ zone.js:739
webpackJsonpCallback @ bootstrap:25
(anonymous) @ 3.iframe.bundle.js:1

System
Environment Info:


  System:
    OS: macOS 11.4
    CPU: (12) x64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
  Binaries:
    Node: 14.15.1 - /usr/local/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 7.13.0 - /usr/local/bin/npm
  Browsers:
    Chrome: 91.0.4472.77
    Firefox: 87.0
    Safari: 14.1.1
  npmPackages:
    @storybook/addon-actions: ^6.3.0-alpha.22 => 6.3.0-alpha.22 
    @storybook/addon-controls: ^6.3.0-alpha.22 => 6.3.0-alpha.22 
    @storybook/addon-docs: ^6.3.0-alpha.22 => 6.3.0-alpha.22 
    @storybook/addon-essentials: ^6.3.0-alpha.22 => 6.3.0-alpha.22 
    @storybook/addon-links: ^6.3.0-alpha.22 => 6.3.0-alpha.22 
    @storybook/angular: ^6.3.0-alpha.22 => 6.3.0-alpha.22 
    @storybook/theming: ^6.3.0-alpha.22 => 6.3.0-alpha.22 

Additional context
I've seen other closed tickets related to this issue (#7544), but the fix is to add "emitDecoratorMetadata": true in tsconfig.json.
This fix doesn't seem to work in my case.

@massi08
Copy link
Author

massi08 commented Jun 11, 2021

Some additional info: The project where this happens is a monorepo powered by Lerna (https://github.com/lerna/lerna#how-it-works).
So in my story when i Import import {RadioComponent, RadioGroupComponent} from '@engie-group/fluid-design-system-angular'; it actually imports the components from a package which is a linked directory in my projet, not from a package downloaded from npm.

@kroeder
Copy link
Member

kroeder commented Jun 14, 2021

Long shot: You use component: RadioGroupComponent and also use RadioComponent in the stories
Doesn't this mean you never actually declare RadioComponent? I wonder why there's no "RadioComponent is not part of an NgModule" error

Can you reproduce this with e.g. a new hello-world component that does nothing but injecting the ChangeDetectorRef?

@massi08
Copy link
Author

massi08 commented Jun 14, 2021

Yes i still get the same issue.

Here's the component:

import {ChangeDetectionStrategy, ChangeDetectorRef, Component} from '@angular/core';

@Component({
  selector: 'nj-test-cdr',
  templateUrl: './test-cdr.component.html',
  styleUrls: ['./test-cdr.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class TestCdrComponent {

  constructor(private cdr: ChangeDetectorRef) {
  }
}

template: test-cdr.component.html

<p>test-cdr works!</p>

its story:

import {TestCdrComponent} from '@engie-group/fluid-design-system-angular';
import {Meta, moduleMetadata, Story} from '@storybook/angular';

export default {
  title: 'TestCdr/Test Cdr',
  component: TestCdrComponent,
  decorators: [
    moduleMetadata({
      declarations: [TestCdrComponent],
    }),
  ],
} as Meta;

export const TestCdr: Story = (args) => ({
  template: `
     <nj-test-cdr></nj-test-cdr>
    `
});

Here's the browser preview with the same error:

image

@massi08
Copy link
Author

massi08 commented Jun 24, 2021

Any news about this issue ? I still have not found a fix yet

@ihor-panasiuk95
Copy link

I also experience a similar issue.
My story
image
My component
image
My service
image

I don't see any errors. I just don't see the story in the preview. But once I comment constructor in ExclusiveFeatureModalService and the body of openExclusiveFeatureModal method in that service, I do see the story in preview. Don't know what happens.
I explicitly set an empty object as ExclusiveFeatureModalService so I expect that the framework won't try to add exactly ExclusiveFeatureModalService but actually it seems like instead of my mock it adds ExclusiveFeatureModalService and this causes the story not showing.
I don't see any specific error in the console that would help me to solve that.
image

@ihor-panasiuk95
Copy link

Note: storybook version is 6.3.4

@massi08
Copy link
Author

massi08 commented Jul 12, 2021

@ihor-panasiuk95 did you try to add ModalWindowService to providers as well ?

@ihor-panasiuk95
Copy link

@massi08 yes

@ihor-panasiuk95
Copy link

when I try to add the full chain of dependencies it works. But when I want to provide mock via { provide: ExclusiveFeatureModalService, useValue: {}} (like in unit-tests) the high-level service it doesn't work.

@ihor-panasiuk95
Copy link

There are no errors. The preview just doesn't display that story in the list. But the rest of stories that cover components without dependencies are displayed normally.

@ihor-panasiuk95
Copy link

My issue was solved. It wasn't related to DI actually. I created the feature request here: #15582

@massi08
Copy link
Author

massi08 commented Oct 18, 2021

@kroeder any news on this I am still experiencing this issue on many of my components using ChangeDetectorRef

@shilman
Copy link
Member

shilman commented Jun 7, 2023

We’re cleaning house! Storybook has changed a lot since this issue was created and we don’t know if it’s still valid. Please open a new issue referencing this one if:

@shilman shilman closed this as not planned Won't fix, can't repro, duplicate, stale Jun 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants