Storybook: Issue with angular Router

Created on 24 Apr 2019  路  11Comments  路  Source: storybookjs/storybook

I'm receiving an error I haven't been able to find my way around. I'm on Storybook 5.0.10 using angular.

Here is the error:

Template parse errors: Can't bind to 'routerLink' since it isn't a known property of 'a'. (" <a *ngIf="tabType === 'link'" [ERROR ->][routerLink]="" [fragment]="tab.id" (click)="!!select(tab.id)" class="util-tabset__li"): ng:///DynamicModule/UtilTabsetComponent.html@20:8 Can't bind to 'fragment' since it isn't a known property of 'a'. (" <a *ngIf="tabType === 'link'" [routerLink]="" [ERROR ->][fragment]="tab.id" (click)="!!select(tab.id)" class="util-tabset__link" "): ng:///DynamicModule/UtilTabsetComponent.html@20:24
Error: Template parse errors:
Can't bind to 'routerLink' since it isn't a known property of 'a'. ("

      <a *ngIf="tabType === 'link'"
        [ERROR ->][routerLink]="" [fragment]="tab.id"
        (click)="!!select(tab.id)"
        class="util-tabset__li"): ng:///DynamicModule/UtilTabsetComponent.html@20:8
Can't bind to 'fragment' since it isn't a known property of 'a'. ("

      <a *ngIf="tabType === 'link'"
        [routerLink]="" [ERROR ->][fragment]="tab.id"
        (click)="!!select(tab.id)"
        class="util-tabset__link"
"): ng:///DynamicModule/UtilTabsetComponent.html@20:24
    at syntaxError (http://localhost:6006/vendors~main.0afdbd165a15faa9fe9e.bundle.js:11068:17)
    at TemplateParser.push../node_modules/@angular/compiler/fesm5/compiler.js.TemplateParser.parse (http://localhost:6006/vendors~main.0afdbd165a15faa9fe9e.bundle.js:29243:19)
    at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._parseTemplate (http://localhost:6006/vendors~main.0afdbd165a15faa9fe9e.bundle.js:34809:37)
    at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._compileTemplate (http://localhost:6006/vendors~main.0afdbd165a15faa9fe9e.bundle.js:34796:23)
    at http://localhost:6006/vendors~main.0afdbd165a15faa9fe9e.bundle.js:34739:62
    at Set.forEach (<anonymous>)
    at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._compileComponents (http://localhost:6006/vendors~main.0afdbd165a15faa9fe9e.bundle.js:34739:19)
    at http://localhost:6006/vendors~main.0afdbd165a15faa9fe9e.bundle.js:34649:19
    at Object.then (http://localhost:6006/vendors~main.0afdbd165a15faa9fe9e.bundle.js:11059:77)
    at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._compileModuleAndComponents (http://localhost:6006/vendors~main.0afdbd165a15faa9fe9e.bundle.js:34648:26)

and here is my story:

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

import { UtilTabDirective } from './util-tab.directive';
import { UtilTabsetComponent } from './util-tabset.component';

// Initiate story
storiesOf('Utility/Tabs/Tab Set', module)
    .addDecorator(
        moduleMetadata({
            declarations: [UtilTabsetComponent, UtilTabDirective],
        }),
    )
    .add('Tab Set', () => ({
        component: UtilTabsetComponent,
        props: {
        },
    }))
angular compatibility with other tools question / support

Most helpful comment

There is no need to mock the RouterLinkWithHref Directive.
Just remember to provide a value for the APP_BASE_HREF token.
Example:

moduleMetadata({
  declarations: [EntityTypeComponent],
  imports: [NgZorroAntdModule, HttpClientModule, RouterModule.forRoot([])],
  providers: [{ provide: APP_BASE_HREF, useValue: '/' }]
})

Use forRoot even if in the original Module you've used forChild.


Or, just discovered, use RouterTestingModule.
Example:

moduleMetadata({
  declarations: [EntityTypeComponent],
  imports: [NgZorroAntdModule, HttpClientModule, RouterTestingModule],
  providers: [{ provide: APP_BASE_HREF, useValue: '/' }]
})

All 11 comments

More an Angular issue that a SB issue but here it is:

You need to add RouterModule to the list of declarations:

moduleMetadata({
   declarations: [UtilTabsetComponent, UtilTabDirective, RouterModule],
}),

Ah okay, thanks. I had that for a little bit but I took it out because I was getting this error:

Unexpected module 'RouterModule' declared by the module 'DynamicModule'. Please add a @Pipe/@Directive/@Component annotation.
Error: Unexpected module 'RouterModule' declared by the module 'DynamicModule'. Please add a @Pipe/@Directive/@Component annotation.
    at syntaxError (http://localhost:6006/vendors~main.fc32f3f8afd5bbb12194.bundle.js:11068:17)
    at http://localhost:6006/vendors~main.fc32f3f8afd5bbb12194.bundle.js:27339:40
    at Array.forEach (<anonymous>)
    at CompileMetadataResolver.push../node_modules/@angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getNgModuleMetadata (http://localhost:6006/vendors~main.fc32f3f8afd5bbb12194.bundle.js:27321:54)
    at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._loadModules (http://localhost:6006/vendors~main.fc32f3f8afd5bbb12194.bundle.js:34667:51)
    at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._compileModuleAndComponents (http://localhost:6006/vendors~main.fc32f3f8afd5bbb12194.bundle.js:34648:36)
    at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler.compileModuleAsync (http://localhost:6006/vendors~main.fc32f3f8afd5bbb12194.bundle.js:34608:37)
    at CompilerImpl.push../node_modules/@angular/platform-browser-dynamic/fesm5/platform-browser-dynamic.js.CompilerImpl.compileModuleAsync (http://localhost:6006/vendors~main.fc32f3f8afd5bbb12194.bundle.js:69540:31)
    at compileNgModuleFactory__PRE_R3__ (http://localhost:6006/vendors~main.fc32f3f8afd5bbb12194.bundle.js:53743:21)
    at PlatformRef.push../node_modules/@angular/core/fesm5/core.js.PlatformRef.bootstrapModule (http://localhost:6006/vendors~main.fc32f3f8afd5bbb12194.bundle.js:53926:16)

I see, your component depends on the router to function (routerLink) you may have to mock the directive for the component to function...
(I have to write a story for a component with routerLink tomorrow, i'll let you know how I get on)

I appreciate it @blemaire, thanks

@taurean I believe your RouterModule should be in the imports array, not the declarations array, i.e.

moduleMetadata({
    imports: [RouterModule],
    declarations: [UtilTabsetComponent, UtilTabDirective],
}),

As the warning indicates, the declarations array is only for, items marked as @Pipe, @Directive, or @Component, not for those marked as @NgModule.

This is almost certainly not an issue caused by anything Storybook is doing.

I'm still struggling to get the component to display but it very well could be an issue with the component itself and is not necessarily storybook related. Closing the ticket, thanks for the help!

Hi @blemaire , did you manage to solve the issue with routerLink? if so, can you please share what you did? Thank you in advance!

@blemaire I too would like to see your solution.

There is no need to mock the RouterLinkWithHref Directive.
Just remember to provide a value for the APP_BASE_HREF token.
Example:

moduleMetadata({
  declarations: [EntityTypeComponent],
  imports: [NgZorroAntdModule, HttpClientModule, RouterModule.forRoot([])],
  providers: [{ provide: APP_BASE_HREF, useValue: '/' }]
})

Use forRoot even if in the original Module you've used forChild.


Or, just discovered, use RouterTestingModule.
Example:

moduleMetadata({
  declarations: [EntityTypeComponent],
  imports: [NgZorroAntdModule, HttpClientModule, RouterTestingModule],
  providers: [{ provide: APP_BASE_HREF, useValue: '/' }]
})

@lppedd
I have tried adding this to my .stories.ts file.

export default {
  title: 'Component',
  decorators: [
    moduleMetadata({
      imports: [RouterTestingModule],
      providers: [{ provide: APP_BASE_HREF, useValue: '/' }],
    }),
  ],
};

And I'm still getting this error in the console

Error: Template parse errors:
Can't bind to 'routerLink' since it isn't a known property of 'a'. ("<a [ERROR ->][routerLink]="['/home']">Home</a>
"): ng:///UiModule/Component.html

This Component is part of a Module, which is being imported on the global storybook config.

addDecorator(
  moduleMetadata({
    imports: [UiModule],
  })
);

@ChazUK I think you need to import the RouterModule in UiModule since you're using routerLink in a component defined in that module.

Was this page helpful?
0 / 5 - 0 ratings