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

[Bug]: Error when trying to create a story for a not standalone component that extends a standalone component #26056

Closed
daryakalenik opened this issue Feb 16, 2024 · 6 comments · Fixed by #27353

Comments

@daryakalenik
Copy link

daryakalenik commented Feb 16, 2024

Describe the bug

I have two components - the Parent component is standalone, the Child one - not standalone. Child extends Parent (class ChildComponent extends ParentComponent) and when I'm trying to create a story for the child I get an error Unexpected directive 'ChildComponent' imported by the module 'StorybookComponentModule'. Please add an @NgModule annotation. If I remove extending from the Child or if I add standalone: true to it the error disappears

To Reproduce

https://stackblitz.com/edit/github-qnhd3h

There's a story for Child component - you can navigate to it using storybook interface

System

System:
    OS: Windows 10 10.0.19045
    CPU: (16) x64 AMD Ryzen 7 PRO 4750G with Radeon Graphics
  Binaries:
    Node: 20.10.0 - C:\Program Files\nodejs\node.EXE
    npm: 10.2.3 - C:\Program Files\nodejs\npm.CMD <----- active
  Browsers:
    Edge: Spartan (44.19041.3636.0), Chromium (121.0.2277.112)
  npmPackages:
    @storybook/addon-essentials: ^7.6.16 => 7.6.16
    @storybook/addon-interactions: ^7.6.16 => 7.6.16
    @storybook/addon-links: ^7.6.16 => 7.6.16
    @storybook/angular: ^7.6.16 => 7.6.16
    @storybook/blocks: ^7.6.16 => 7.6.16
    @storybook/test: ^7.6.16 => 7.6.16
    storybook: ^7.6.16 => 7.6.16

Additional context

No response

@valentinpalkovic
Copy link
Contributor

Can you check out the latest Storybook 8 beta? AFAIK it has some Angular improvements. npx storybook@next upgrade

@daryakalenik
Copy link
Author

@valentinpalkovic thanks for the suggestion! But unfortunately it didn't help, just tried it :(

@gobeli
Copy link

gobeli commented Mar 28, 2024

I managed to work around this issue by creating a dummy standalone component inside the story file. And then using that component in the story.

@Component({
  standalone: true,
  imports: [RealComponentWhichExtendsOther],
  template: `
    <app-real></app-real>
  `,
})
class DummyComponent {}

export default {
  component: DummyComponent,
  title: 'RealComponent',
};

@Marklb
Copy link
Member

Marklb commented Mar 28, 2024

I think I see what is happening and it does appear to be a bug.

I can't remember exactly how Angular handles the class decorator, when extending a class. If I am remembering correctly, though, it doesn't look at anything, other than the decorator that is added to the class directly. I would need to confirm, before I can say that is actually correct.

Assuming my understanding is correct, then Storybook's usage of reflectionCapabilities.annotations is incorrect. Storybook is iterating all decorators, to determine if the class is a Component, Directive or Pipe and if it is standalone. In this situation, there are two component decorators and at least one contains standalone: true, so Storybook is considering it to be a standalone component.

@gobeli
Copy link

gobeli commented Mar 28, 2024

Ah, I think your right. At least in my case the parent component is standalone and from what I can remember, it is the case that only the decorator on the actual component counts. I've got it to work inside the tests of the codebase by using the private method _ownAnnotations from Angular ReflectionCapabilities (https://github.com/angular/angular/blob/ddbf6bb038d101daf5280abbd2a0efaa0b7fd3a0/packages/core/src/reflection/reflection_capabilities.ts#L180C11-L180C26) and adding a Testcase. But it's probably not a good idea to use a private api...

@dario-baumberger
Copy link
Contributor

dario-baumberger commented May 24, 2024

We have found a solution. You are welcome to try it and see if it works for you.

It's not a sustainable solution, but it would be interesting to know if it works everywhere. My testing capabilities were very limited...

Manually apply the changes from the pull request https://github.com/storybookjs/storybook/pull/27353/files#diff-4ff611f840cb60ea92c0c47c5e7fced91a9f8d4a57fea7c9b7d3e7b5b97c46ca in ./node_modules/@storybook/angular/dist/client/angular-beta/utils/PropertyExtractor.js

Replace

const isStandalone = (isComponent || isDirective) && decorators.some((d) => d.standalone)

With

 const isStandalone = !!(
      (isComponent || isDirective) &&
      [...decorators]
        .reverse()
        .find(
          (d) =>
            _a.isDecoratorInstanceOf(d, 'Component') || _a.isDecoratorInstanceOf(d, 'Directive')
        )?.standalone);

Hopefully, this will be fixed in one of the upcoming releases. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

6 participants