storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
84.7k stars 9.33k forks source link

[Bug]: SB7 Angular for a component throws: Type XComponent is part of the declarations of 2 modules #21873

Closed rezoled closed 1 year ago

rezoled commented 1 year ago

Describe the bug

When creating a simple story with the new recommended annotation for Angular (described here: https://github.com/storybookjs/storybook/blob/v7.0.0-rc.11/MIGRATION.md#angular-application-providers-and-modulewithproviders), angular throws the following error:

Type AvatarComponent is part of the declarations of 2 modules: AvatarModule and StorybookComponentModule! Please consider moving AvatarComponent to a higher module that imports AvatarModule and StorybookComponentModule. You can also create a new NgModule that exports and includes AvatarComponent then import that NgModule in AvatarModule and StorybookComponentModule.

To Reproduce

Story:

export default {
    component: AvatarComponent,
    decorators: [
        applicationConfig({
            providers: [importProvidersFrom(AvatarModule)],
        }),
    ],
} as Meta;

Module:

import { NgModule } from '@angular/core';
import { AvatarComponent } from './avatar.component';

@NgModule({
    declarations: [AvatarComponent],
    exports: [AvatarComponent],
})
export class AvatarModule {}

System

No response

Additional context

No response

rezoled commented 1 year ago

@valentinpalkovic Opened a new issue as requested

valentinpalkovic commented 1 year ago

@rezoled Can you provide a minimal reproduction?

rezoled commented 1 year ago

Here it is in my private account: https://github.com/roypeled/sb7-bug

DanK1368 commented 1 year ago

Just did the migration to Storybook 7, and having the same issue with Angular

franknwankwo commented 1 year ago

just installed Storybook 7 and I'm having the same issue when attempting imports.

decorators: [
    moduleMetadata({
      // declarations: [],
      imports: [
      StorybookTranslateModule,
      ],
    }),
  ],
valentinpalkovic commented 1 year ago

Hey @rezoled,

Thank you for the reproduction. I think your usecase does not make much sense, because there are no providers, which can be extracted from AvatarModule, therefore importing it in combination with importProvidersFrom helper function does not make much sense. Can you give me a more realistic example?

valentinpalkovic commented 1 year ago

@DanK1368 Can you describe your exact use case? Maybe you can share your stories file and the component and module you try to set up for the story.

valentinpalkovic commented 1 year ago

@franknwankwo Can you share the contents of StorybookTranslateModule and could you also share your whole Story content?

rezoled commented 1 year ago

Hey @rezoled,

Thank you for the reproduction. I think your usecase does not make much sense, because there are no providers, which can be extracted from AvatarModule, therefore importing it in combination with importProvidersFrom helper function does not make much sense. Can you give me a more realistic example?

I wanted to create the simplest use case, would adding providers solve the problem? This error still happens which much more complicated modules.

valentinpalkovic commented 1 year ago

@rezoled If AvatarModule is not a pure service that contains providers, but actually deals as a packager to package all necessary components/directives into a single unit and your angular component depends on it, it would be still necessary to add it to the imports section of moduleMetadata. The importProvidersFrom helper function only extracts providers and does not register components/pipes/directives. What happens, if you add AvatarModule to moduleMetadata?

export default {
    component: AvatarComponent,
    decorators: [
                moduleMetadata({
                  imports: [AvatarModule]
                }),
        applicationConfig({
            providers: [importProvidersFrom(AvatarModule)],
        }),
    ],
} as Meta;

And if AvatarModule does not have providers, which have to be registered on an environmental level, you don't have to use the applicationConfig to register the providers environment-wide.

rezoled commented 1 year ago

Ahhh I see. Your suggestion works, it makes sense.

Maybe add in the documentation a specific page the explains what applicationConfig does and its usage with root modules (such as router and animation)?