Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Storybook Component is part of two modules error

I'm testing the UI on some shared components with Storybook and running into a bug where it appears that Storybook is loading the component into the DynamicModule, resulting in the following error:

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

The DigFinder component is definitely only declared in its module:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DigFinderComponent } from './components/dig-finder/dig-finder.component';
import { DigFinderPanelComponent } from './components/dig-finder-panel/dig-finder-panel.component';
import { DigFinderNodeComponent } from './components/dig-finder-node/dig-finder-node.component';
import {DigUiModule} from '../dig-ui/dig-ui.module';
import {DigCardModule} from '../dig-card/dig-card.module';
import {DigContainerModule} from '../dig-container/dig-container.module';
import {DigBreadcrumbsModule} from '../dig-breadcrumbs/dig-breadcrumbs.module';
import {RouterModule} from '@angular/router';

@NgModule({
  declarations: [DigFinderComponent, DigFinderPanelComponent, DigFinderNodeComponent],
  imports: [
    CommonModule,
    DigBreadcrumbsModule,
    DigCardModule,
    DigContainerModule,
    DigUiModule,
    RouterModule
  ],
  exports: [
    DigFinderComponent
  ]
})
export class DigFinderModule { }

The unit tests are all passing, but this error comes up when its rendered by storybook:

import {moduleMetadata, storiesOf} from '@storybook/angular';

import {withNotes} from '@storybook/addon-notes';
import {action} from '@storybook/addon-actions';
import {DigFinderModule} from '../../../src/modules/dig/dig-finder/dig-finder.module';
import {DigFinderComponent} from '../../../src/modules/dig/dig-finder/components/dig-finder/dig-finder.component';

const testData = [
  '/about',
  '/about/team',
  '/about/services',
]
storiesOf('DigFinder', module)
  .addDecorator(
    moduleMetadata({
      imports: [
        DigFinderModule,
      ]
    })
  )
  .add('Default', () => ({
    component: DigFinderComponent,
    props: {
      data: testData,
      select: action('Selected: ')
    }
  }));
like image 288
ForrestLyman Avatar asked Jan 22 '19 19:01

ForrestLyman


2 Answers

This is happening because you're using the component prop inside of the Storybook add method. I believe that's how it ends up in DynamicModule, and then moduleMetadata's import is getting it the second way.

One solution is to do what you answered: skip importing the module and declare/import the bits of the module that you need. The alternative is to use the template prop instead of the component prop:

import {moduleMetadata, storiesOf} from '@storybook/angular';

import {withNotes} from '@storybook/addon-notes';
import {action} from '@storybook/addon-actions';
import {DigFinderModule} from '../../../src/modules/dig/dig-finder/dig-finder.module';
import {DigFinderComponent} from '../../../src/modules/dig/dig-finder/components/dig-finder/dig-finder.component';

const testData = [
  '/about',
  '/about/team',
  '/about/services',
]
storiesOf('DigFinder', module)
  .addDecorator(
    moduleMetadata({
      imports: [
        DigFinderModule,
      ]
    })
  )
  .add('Default', () => ({
    template: `
      <app-dig-finder
        [data]="data"
      ></app-dig-finder>
    `,
    props: {
      data: testData,
    }
  }));

Note that you still needs props here.

like image 158
Brendan Avatar answered Oct 12 '22 02:10

Brendan


I was able to resolve this by explicitly importing all of the requirements, rather than importing the module:

storiesOf('DigFinder', module)
  .addDecorator(
    moduleMetadata({
      declarations: [DigFinderComponent, DigFinderPanelComponent, DigFinderNodeComponent],
      imports: [
        CommonModule,
        DigBreadcrumbsModule,
        DigCardModule,
        DigContainerModule,
        DigUiModule,
        RouterModule
      ],
    })
  )
  .add('Default', () => ({
    component: DigFinderComponent,
    props: {
      data: testData,
      select: action('Selected: ')
    }
  }));

But would still like to figure out why the module import doesnt work (its working on several other examples).

like image 34
ForrestLyman Avatar answered Oct 12 '22 02:10

ForrestLyman