-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13939 from storybookjs/angular/component-without-…
…selector Angular: Support angular components without selector
- Loading branch information
Showing
11 changed files
with
343 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
...ent-without-selector/__snapshots__/without-selector-ng-component-outlet.stories.storyshot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Storyshots Basics / Component / without selector / Custom wrapper *NgComponentOutlet Custom wrapper *NgComponentOutlet 1`] = ` | ||
<storybook-wrapper> | ||
<ng-component-outlet-wrapper | ||
ng-reflect-color="green" | ||
ng-reflect-component-outlet="function WithoutSelectorCompon" | ||
ng-reflect-name="Dixie Normous" | ||
> | ||
|
||
<ng-component> | ||
My name in color : | ||
<div | ||
style="color: green;" | ||
> | ||
Dixie Normous | ||
</div> | ||
Ng-content : Inspired by | ||
https://angular.io/api/common/NgComponentOutlet | ||
</ng-component> | ||
</ng-component-outlet-wrapper> | ||
</storybook-wrapper> | ||
`; |
17 changes: 17 additions & 0 deletions
17
...ent-without-selector/__snapshots__/without-selector-ng-factory-resolver.stories.storyshot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Storyshots Basics / Component / without selector / Custom wrapper ComponentFactoryResolver Custom wrapper ComponentFactoryResolver 1`] = ` | ||
<storybook-wrapper> | ||
<component-factory-wrapper | ||
ng-reflect-args="[object Object]" | ||
ng-reflect-component-outlet="function WithoutSelectorCompon" | ||
/><ng-component> | ||
My name in color : | ||
<div | ||
style="color: chartreuse;" | ||
> | ||
Dixie Normous | ||
</div> | ||
</ng-component> | ||
</storybook-wrapper> | ||
`; |
27 changes: 27 additions & 0 deletions
27
...tories/basics/component-without-selector/__snapshots__/without-selector.stories.storyshot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Storyshots Basics / Component / without selector Simple Component 1`] = ` | ||
<storybook-wrapper> | ||
<ng-component> | ||
My name in color : | ||
<div | ||
style="color: rgb(30, 136, 229);" | ||
> | ||
Joe Bar | ||
</div> | ||
</ng-component> | ||
</storybook-wrapper> | ||
`; | ||
|
||
exports[`Storyshots Basics / Component / without selector With Injection Token And Args 1`] = ` | ||
<storybook-wrapper> | ||
<ng-component> | ||
My name in color : | ||
<div | ||
style="color: red;" | ||
> | ||
Dixie Normous | ||
</div> | ||
</ng-component> | ||
</storybook-wrapper> | ||
`; |
75 changes: 75 additions & 0 deletions
75
...stories/basics/component-without-selector/without-selector-ng-component-outlet.stories.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { Component, Injector, Input, OnInit, Type } from '@angular/core'; | ||
import { componentWrapperDecorator, moduleMetadata, Story, Meta } from '@storybook/angular'; | ||
import { WithoutSelectorComponent, WITHOUT_SELECTOR_DATA } from './without-selector.component'; | ||
|
||
export default { | ||
title: 'Basics / Component / without selector / Custom wrapper *NgComponentOutlet', | ||
component: WithoutSelectorComponent, | ||
decorators: [ | ||
moduleMetadata({ | ||
entryComponents: [WithoutSelectorComponent], | ||
}), | ||
], | ||
} as Meta; | ||
|
||
// Advanced example with custom *ngComponentOutlet | ||
|
||
@Component({ | ||
selector: 'ng-component-outlet-wrapper', | ||
template: `<ng-container | ||
*ngComponentOutlet="componentOutlet; injector: componentInjector; content: componentContent" | ||
></ng-container>`, | ||
}) | ||
class NgComponentOutletWrapperComponent implements OnInit { | ||
@Input() | ||
componentOutlet: Type<unknown>; | ||
|
||
@Input() | ||
name: string; | ||
|
||
@Input() | ||
color: string; | ||
|
||
componentInjector: Injector; | ||
|
||
componentContent = [ | ||
// eslint-disable-next-line no-undef | ||
[document.createTextNode('Ng-content : Inspired by ')], | ||
// eslint-disable-next-line no-undef | ||
[document.createTextNode('https://angular.io/api/common/NgComponentOutlet')], | ||
]; | ||
|
||
// eslint-disable-next-line no-useless-constructor | ||
constructor(private readonly injector: Injector) {} | ||
|
||
ngOnInit(): void { | ||
this.componentInjector = Injector.create({ | ||
providers: [ | ||
{ provide: WITHOUT_SELECTOR_DATA, useValue: { color: this.color, name: this.name } }, | ||
], | ||
parent: this.injector, | ||
}); | ||
} | ||
} | ||
|
||
// Live changing of args by controls does not work at the moment. When changing args storybook does not fully | ||
// reload and therefore does not take into account the change of provider. | ||
export const WithCustomNgComponentOutletWrapper: Story = (args) => ({ | ||
props: args, | ||
}); | ||
WithCustomNgComponentOutletWrapper.storyName = 'Custom wrapper *NgComponentOutlet'; | ||
WithCustomNgComponentOutletWrapper.argTypes = { | ||
name: { control: 'text' }, | ||
color: { control: 'color' }, | ||
}; | ||
WithCustomNgComponentOutletWrapper.args = { name: 'Dixie Normous', color: 'green' }; | ||
WithCustomNgComponentOutletWrapper.decorators = [ | ||
moduleMetadata({ | ||
declarations: [NgComponentOutletWrapperComponent], | ||
}), | ||
componentWrapperDecorator(NgComponentOutletWrapperComponent, (args) => ({ | ||
name: args.name, | ||
color: args.color, | ||
componentOutlet: WithoutSelectorComponent, | ||
})), | ||
]; |
72 changes: 72 additions & 0 deletions
72
...stories/basics/component-without-selector/without-selector-ng-factory-resolver.stories.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import { | ||
AfterViewInit, | ||
Component, | ||
ComponentFactoryResolver, | ||
Input, | ||
Type, | ||
ViewChild, | ||
ViewContainerRef, | ||
} from '@angular/core'; | ||
import { componentWrapperDecorator, moduleMetadata, Story, Meta } from '@storybook/angular'; | ||
|
||
import { WithoutSelectorComponent } from './without-selector.component'; | ||
|
||
export default { | ||
title: 'Basics / Component / without selector / Custom wrapper ComponentFactoryResolver', | ||
component: WithoutSelectorComponent, | ||
decorators: [ | ||
moduleMetadata({ | ||
entryComponents: [WithoutSelectorComponent], | ||
}), | ||
], | ||
} as Meta; | ||
|
||
// Advanced example with custom ComponentFactoryResolver | ||
|
||
@Component({ selector: 'component-factory-wrapper', template: '' }) | ||
class ComponentFactoryWrapperComponent implements AfterViewInit { | ||
@ViewChild('dynamicInsert', { read: ViewContainerRef }) dynamicInsert; | ||
|
||
@Input() | ||
componentOutlet: Type<unknown>; | ||
|
||
@Input() | ||
args: any; | ||
|
||
// eslint-disable-next-line no-useless-constructor | ||
constructor( | ||
private viewContainerRef: ViewContainerRef, | ||
private componentFactoryResolver: ComponentFactoryResolver | ||
) {} | ||
|
||
ngAfterViewInit() { | ||
const componentFactory = this.componentFactoryResolver.resolveComponentFactory( | ||
this.componentOutlet | ||
); | ||
const containerRef = this.viewContainerRef; | ||
containerRef.clear(); | ||
const dynamicComponent = containerRef.createComponent(componentFactory); | ||
Object.assign(dynamicComponent.instance, this.args); | ||
} | ||
} | ||
|
||
// Live changing of args by controls does not work at the moment. When changing args storybook does not fully | ||
// reload and therefore does not take into account the change of provider. | ||
export const WithComponentFactoryResolver: Story = (args) => ({ | ||
props: args, | ||
}); | ||
WithComponentFactoryResolver.storyName = 'Custom wrapper ComponentFactoryResolver'; | ||
WithComponentFactoryResolver.argTypes = { | ||
name: { control: 'text' }, | ||
color: { control: 'color' }, | ||
}; | ||
WithComponentFactoryResolver.args = { name: 'Dixie Normous', color: 'chartreuse' }; | ||
WithComponentFactoryResolver.decorators = [ | ||
moduleMetadata({ | ||
declarations: [ComponentFactoryWrapperComponent], | ||
}), | ||
componentWrapperDecorator(ComponentFactoryWrapperComponent, ({ args }) => ({ | ||
args, | ||
componentOutlet: WithoutSelectorComponent, | ||
})), | ||
]; |
30 changes: 30 additions & 0 deletions
30
...s/angular-cli/src/stories/basics/component-without-selector/without-selector.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { Component, Inject, InjectionToken, Optional } from '@angular/core'; | ||
|
||
export const WITHOUT_SELECTOR_DATA = new InjectionToken<{ color: string; name: string }>( | ||
'WITHOUT_SELECTOR_DATA' | ||
); | ||
|
||
@Component({ | ||
template: `My name in color : | ||
<div [style.color]="color">{{ name }}</div> | ||
<ng-content></ng-content> <ng-content></ng-content>`, | ||
}) | ||
export class WithoutSelectorComponent { | ||
color = '#1e88e5'; | ||
|
||
name = 'Joe Bar'; | ||
|
||
constructor( | ||
@Inject(WITHOUT_SELECTOR_DATA) | ||
@Optional() | ||
data: { | ||
color: string; | ||
name: string; | ||
} | null | ||
) { | ||
if (data) { | ||
this.color = data.color; | ||
this.name = data.name; | ||
} | ||
} | ||
} |
Oops, something went wrong.