Open krbaio3 opened 3 years ago
I don't know the current state of this issue, but I do know that we no longer support Angular 11. If somebody is experiencing this problem with Angular 14, 15, or 16 and Storybook 7.0+, please open an issue with a reproduction and we'd be happy to take a look at it. To create a reproduction, go to https://storybook.new or see repro docs. Thank you! 🙏
Hey @shilman - This issue is still being experienced on Angular 14, 15, and 16 with Storybook 7+ when using npm 7+. I have created a reproduction based on @John-Zimmer's instructions here: Reproduction Repository.
If you'd prefer I create a new issue with this reproduction, I can also do that instead.
If additional information is needed, please let me know.
@computergnome99 did you create a new issue for this? Seems still valid as we are also still seeing this with Angular 15.2.0, Storybook 7.0.6, NPM 8.19.3 and Windows.
thanks @computergnome99 @tlaukkanen !!!
I generally never comment on GitHub but thought to help get this issue raised.
Using: NodeJs: 16.20.0 Npm: 8.19.4 Angular: ^16.0.4 (takes 16.1.1) storybook: ~7.0.22
I got the error listed in the main post during running the storybook website trying to render a component.
After deleting all package lock and node modules folder, and doing npm install —legacy-peer-reps it fixed all my issues after running storybook.
@jesse-schein Thanks for the confirmation!
@jesse-schein solution works with npm. But in our monorepo we are using pnpm and I cannot find a way to make it work. We are using the last versions of Angular and Storybook with Nx.
Hello, I'm facing the same issue with Nx, I tried to use storybook in the libs folder.
Angular: 16.1.0 Storybook: 7.1.0 Nodejs: 16.16.0
I can confirm the problem using storybook inside an angular-workspace
with more projects, the workaround of @John-Zimmer in https://github.com/storybookjs/storybook/issues/14828#issuecomment-1523875596 works for me.
In my case I don't need to add flags to npm
, but just removing the node_modules
from the project directory and doing again a fresh npm install
in the workspace root, fixes the problem. Maybe this is related to my version of npm
being a little older.
My environment is:
Storybook 7.3.2
Angular CLI: 15.2.9
Node: 16.14.2
Package Manager: npm 8.5.0
OS: linux x64
I did some debugging and in my case the problem is in the function computesTemplateFromComponent: the ngComponentMetadata
is undefined.
const ngComponentMetadata = getComponentDecoratorMetadata(component); //undefined for me
Debugging a little more inside the getComponentDecoratorMetadata
function:
export const getComponentDecoratorMetadata = (component: any): Component | undefined => {
const decorators = reflectionCapabilities.annotations(component); //correctly populated
return decorators.reverse().find((d) => d instanceof Component); //failing on the test function
};
I see the decorators
const correctly populated with a decorator object, but then the subsequent find()
returns undefined
.
I hope this could help identify the problem.
I can confirm this error, but I have a bit more information.
We started having this error after moving from Angular 12 to Angular 15, but, well, we ALSO decided to migrate to Storybook v7 at the same time.
So I'm in the unique position to confirm that this happens in both 6.5.16, AND 7.3.2, in the same project, after migrating to Angular 15.
Angular CLI: 15.2.8 Node: 16.20.2 Package Manager: npm 8.19.4 OS: win32 x64
Storybook: Both 6.5.16 AND 7.3.2, (But 7.3.2 only has this issue in a builded PROD, not dev. While 6.5.16 has this issue in DEV too.)
Running npm install --legacy-peer-deps didn't work for me. Any chance someone could post their package.json?
Did anyone successfully solve this issue?
I am facing the same problem as @EliezerB123.
Storybook Version: 7.4.5 Node Version: 18.17.0 npm Version: 8.3.0
Starting storybook in dev mode works perfectly fine. Running a production build and deploying the result files leads to the error.
However, I encountered the following:
When I use a story with the component
attribute, the error occurs.
Example:
export Default {
component: ButtonComponent
} as Meta;
Stories where I used a template instead of the component reference work as expected. Example:
const Template: StoryFn<ButtonComponent> = (args: ButtonComponent) => ({
props: {
...args,
},
template: '<ic-one-button></ic-one-button>'
});
@atropo
I did some debugging and in my case the problem is in the function computesTemplateFromComponent: the
ngComponentMetadata
is undefined.const ngComponentMetadata = getComponentDecoratorMetadata(component); //undefined for me
Debugging a little more inside the
getComponentDecoratorMetadata
function:export const getComponentDecoratorMetadata = (component: any): Component | undefined => { const decorators = reflectionCapabilities.annotations(component); //correctly populated return decorators.reverse().find((d) => d instanceof Component); //failing on the test function };
I see the
decorators
const correctly populated with a decorator object, but then the subsequentfind()
returnsundefined
.I hope this could help identify the problem.
From what I can tell, this seems to be the likely source of the bug. As per https://stackoverflow.com/a/63937850/5243309 and https://stackoverflow.com/q/41587865/5243309, it seems that instanceof Component will fail when using two node_modules/@angular
folders, or when a library has its own instance of node_modules/@angular
because it has Angular listed in dependencies
instead of peerDependencies
. ( link#3 )
Which explains why npm install --legacy-peer-deps appears to solve the issue for some people.
The solution seems to be to replace all the code using instanceOf
with something like this:
decorator.constructor.name === factory.prototype.constructor.name
.
Hi, i'm facing the same problem. It occurs only when running a production build :'( This error appearred when i migrated from 7.0 to 7.4.6. Here are the versions I use now :
Storybook Version: 7.4.6 Node Version: 18.16.0 npm Version: 9.5.1 Angular 16.2
HI, found solution.
Change imports for stand alone at .stories.ts
from: import { Component } from '@xm-ngx/components/component';
to : import { Component } from './component.component';
I hope this could help.
@atropo
I did some debugging and in my case the problem is in the function computesTemplateFromComponent: the
ngComponentMetadata
is undefined.const ngComponentMetadata = getComponentDecoratorMetadata(component); //undefined for me
Debugging a little more inside the
getComponentDecoratorMetadata
function:export const getComponentDecoratorMetadata = (component: any): Component | undefined => { const decorators = reflectionCapabilities.annotations(component); //correctly populated return decorators.reverse().find((d) => d instanceof Component); //failing on the test function };
I see the
decorators
const correctly populated with a decorator object, but then the subsequentfind()
returnsundefined
. I hope this could help identify the problem.From what I can tell, this seems to be the likely source of the bug. As per https://stackoverflow.com/a/63937850/5243309 and https://stackoverflow.com/q/41587865/5243309, it seems that instanceof Component will fail when using two
node_modules/@angular
folders, or when a library has its own instance ofnode_modules/@angular
because it has Angular listed independencies
instead ofpeerDependencies
. ( link#3 )Which explains why npm install --legacy-peer-deps appears to solve the issue for some people.
The solution seems to be to replace all the code using
instanceOf
with something like this:decorator.constructor.name === factory.prototype.constructor.name
.
Initially, I thought the same, and I already prepared a PR to not use instanceof
checks but instead rely on some type of information, which is appended during compilation to the decorator properties.
I talked to the Angular core team, and they warned me to support this case since having multiple instances of Angular in the application is a quite broken state, and many things are likely to malfunction. The only valid solution, therefore, is to guarantee that the application loads one instance of Angular.
So I thought about the reproduction, which was provided by @John-Zimmer. When creating an Angular workspace with some applications and libraries, each library might have its dependencies, which we must install. Since npm's default behavior is to install peer dependencies, a npm install
in a library folder will install @angular/core
as well. This is NOT what we want. The whole workspace should refer to one @angular/core
instance, not multiple ones. So what happens if we use npm's workspace feature here? Let's go to the root package.json and let's add all project folders as a workspace:
{
...
"workspaces": [
"projects/*"
],
...
}
Then, a npm install
is only executed at the root level, never in a library folder. Dependencies will automatically be hoisted to the root's node_module folder, and conflicting dependencies will remain in the lib's node_modules. This guarantees that we always have one instance of @angular/core
installed and used. Does anyone know, whether there are some arguments against this approach?
NX, on the other side, has its Single Version Policy, where all dependencies are installed in the root folder. Hence, the mentioned issues with having multiple instances of Angular should never occur. But there seem to be issues, and I am curious whether @yayassa-tootelo or @DanielAlcaraz could provide a reproduction with nx. But also, in this case, I suggest using the workspace feature of the used package manager to resolve this issue.
Since the 7.5.0 storybook release, it is now possible to use the argsToTemplate
method for property and event Bindings.
In our case, this has been used as a workaround for the error Cannot read property 'selector' of undefined
.
Here is an example of how to use it :
import { argsToTemplate } from '@storybook/angular';
export const ExampleRange: Story = {
name: 'Default',
args: {
stringProp: "Foo",
objectProp : {foo: "bar"},
arrayProp: ["Foo", "Bar"]
},
render: (args) => ({
props: args,
template: `<app-my-input ${argsToTemplate(args)}></app-my-input>`
})
};
Using this on all of our stories seems to work, and we haven't found any problems at the moment.
Hope this helps.
Versions : Storybook Version: 7.5.0 Node Version: 18.16.0 npm Version: 9.5.1 Angular 16.2.8
@atropo
I did some debugging and in my case the problem is in the function computesTemplateFromComponent: the
ngComponentMetadata
is undefined.const ngComponentMetadata = getComponentDecoratorMetadata(component); //undefined for me
Debugging a little more inside the
getComponentDecoratorMetadata
function:export const getComponentDecoratorMetadata = (component: any): Component | undefined => { const decorators = reflectionCapabilities.annotations(component); //correctly populated return decorators.reverse().find((d) => d instanceof Component); //failing on the test function };
I see the
decorators
const correctly populated with a decorator object, but then the subsequentfind()
returnsundefined
. I hope this could help identify the problem.From what I can tell, this seems to be the likely source of the bug. As per https://stackoverflow.com/a/63937850/5243309 and https://stackoverflow.com/q/41587865/5243309, it seems that instanceof Component will fail when using two
node_modules/@angular
folders, or when a library has its own instance ofnode_modules/@angular
because it has Angular listed independencies
instead ofpeerDependencies
. ( link#3 ) Which explains why npm install --legacy-peer-deps appears to solve the issue for some people. The solution seems to be to replace all the code usinginstanceOf
with something like this:decorator.constructor.name === factory.prototype.constructor.name
.Initially, I thought the same, and I already prepared a PR to not use
instanceof
checks but instead rely on some type of information, which is appended during compilation to the decorator properties.I talked to the Angular core team, and they warned me to support this case since having multiple instances of Angular in the application is a quite broken state, and many things are likely to malfunction. The only valid solution, therefore, is to guarantee that the application loads one instance of Angular.
So I thought about the reproduction, which was provided by @John-Zimmer. When creating an Angular workspace with some applications and libraries, each library might have its dependencies, which we must install. Since npm's default behavior is to install peer dependencies, a
npm install
in a library folder will install@angular/core
as well. This is NOT what we want. The whole workspace should refer to one@angular/core
instance, not multiple ones. So what happens if we use npm's workspace feature here? Let's go to the root package.json and let's add all project folders as a workspace:{ ... "workspaces": [ "projects/*" ], ... }
Then, an
npm install
is only executed at the root level, never in a library folder. Dependencies will automatically be hoisted to the root's node_module folder, and conflicting dependencies will remain in the lib's node_modules. This guarantees that we always have one instance of@angular/core
installed and used. Does anyone know, whether there are some arguments against this approach?NX, on the other side, has its Single Version Policy, where all dependencies are installed in the root folder. Hence, the mentioned issues with having multiple instances of Angular should never occur. But there seem to be issues, and I am curious whether @yayassa-tootelo or @DanielAlcaraz could provide a reproduction with nx. But also, in this case, I suggest using the workspace feature of the used package manager to resolve this issue.
Is there a repo or a stackblitz/codesandbox with working code?
The only thing that fixed it for me was switching enableProdMode
to false
in angular.json. Not amazing but quick work around until this gets figured out for sure. I'm not using a monorepo either.
Maybe it helps anyone: I had the same issue. I have a Angular mono repo for libraries and storybook installed at the root. I accidentally run npm i
once within a library folder, so that I had a node_modules folder at the root and within the library. Deleting node_modules within the library and only run npm i
at root fixed it for me.
Is a solution in the works ? The only solution working for us actually is to set a template instead of using the component directly, but it's not a solution for long term.
Versions : Storybook Version: 7.6.7 Node Version: 18.18.2 npm Version: 9.8.1 Angular 17.0.8
This is still happening. Tried a few options Node v18.18.0 Storybook: 7.6.4
Another clue: It works in my local for both approach. Error shows up when I deploy this. Update: I've fix it now.
@ranceroxas Have you read my comment here: https://github.com/storybookjs/storybook/issues/14828#issuecomment-1770336203. Please make sure that only one instance of Angular is used in the monorepo. Otherwise, disabling prod mode like mentioned in other comments might help as well.
@vasa-ae, Can you tell me how your repository structure looks? If you use a mono repo, does this comment help? The main issue is that you likely have multiple Angular instances in your repository in different node_module folders. Ensure that just one instance of @angular
dependencies is installed, and then the issue should go away.
Thank you for providing all this information.
First, I want to clarify that loading stories from "node_modules" isn't officially supported. We often explicitly exclude running builder plugins/loaders for node_module
files because of performance reasons.
Second, could you run npm why @angular/core
or yarn why @angular/core
, depending of your package manager.
Could you also initialize Storybook in your library @aea/angular-shared-library
instead? Does the error disappear if you would do so (also for testing purposes)?
Hi everyone, I'm facing the same issue using Angular@16, pnpm workspace and StoryBook@8.
I have made a reproductible repo here.
To try it out:
pnpm install
on the root workspacepnpm start
Hope it will help for debugging.
@valentinpalkovic I have make sure that, in the Angular UI lib, angular is a peerDependency and with a pnpm why @angular/core
there is only 1 version of angular installed 16.2.12.
I have no error in dev it's only with the builded storybook. (You can try pnpm storybook
)
Hi everyone, I'm facing the same issue using Angular@16, pnpm workspace and StoryBook@8.
I have made a reproductible repo here.
To try it out:
pnpm install
on the root workspacepnpm start
Hope it will help for debugging.
@valentinpalkovic I have make sure that, in the Angular UI lib, angular is a peerDependency and with a
pnpm why @angular/core
there is only 1 version of angular installed 16.2.12.I have no error in dev it's only with the builded storybook. (You can try
pnpm storybook
)
@valentinpalkovic, are this exemple good for debugging what is the error ?
Having the same issue here, any workarounds on this? Using storybook 8.2.9 with angular 16. It def look like its the build of storybook that is giving this error for components used within stories.
Describe the bug When I generate a component in an angular library (ng11), and I am going to use it in a storybook, it shows me the error of:
Cannot read property 'selector' of undefined.
To Reproduce https://github.com/krbaio3/sb-lib-issue
System System: OS: macOS 11.3.1 CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz Binaries: Node: 15.14.0 - ~/.nvm/versions/node/v15.14.0/bin/node Yarn: 1.22.10 - /usr/local/bin/yarn npm: 7.11.2 - ~/.nvm/versions/node/v15.14.0/bin/npm Browsers: Chrome: 90.0.4430.93 Firefox: 88.0 Safari: 14.1 npmPackages: @storybook/addon-actions: ^6.2.9 => 6.2.9 @storybook/addon-essentials: ^6.2.9 => 6.2.9 @storybook/addon-links: ^6.2.9 => 6.2.9 @storybook/angular: ^6.2.9 => 6.2.9
Additional context
Create an angular project:
ng new design-system --create-application=false --prefix=ds --style=scss
Create a angular-lib:
ng generate library pattern-lib --prefix=pl
Change the
name
ofdesign-system/projects/pattern-lib/package.json
to@css/pattern-lib
Change the
path
property ofdesign-system/tsconfig.json
frompattern-lib
to@css/pattern-lib
Generate the component
ng generate component button --project=pattern-lib
My button component is:
Change tsconfig properties of
design-system/projects/pattern-lib/tsconfig.lib.json
. Add this property:Generate the lib dist:
ng build
Init the storybook with
npx -p @storybook/cli sb init --type angular
Generate my custom story:
MyButton.stories.ts
I run:
npm run storybook
If I run with this code, (import { ButtonComponent } from 'projects/pattern-lib/src/public-api';) the storybook works.
But, if I change the import (commented) import { ButtonComponent } from '@css/pattern-lib'; the storybook fails, with the error Cannot read property 'selector' of undefined