feat(@schematics/angular): add type option to component generator (#15754)

the type option allows you to change the default .component.ts suffix to new types.
such as

Route
Dialog
UI
Container
This commit is contained in:
Leon Radley 2019-10-09 20:09:12 +02:00 committed by Minko Gechev
parent 970e2055c0
commit c0d42e0c0e
8 changed files with 52 additions and 32 deletions

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { <%= classify(name) %><%= classify(type) %> } from './<%= dasherize(name) %>.<%= dasherize(type) %>';
describe('<%= classify(name) %><%= classify(type) %>', () => {
let component: <%= classify(name) %><%= classify(type) %>;
let fixture: ComponentFixture<<%= classify(name) %><%= classify(type) %>>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ <%= classify(name) %><%= classify(type) %> ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(<%= classify(name) %><%= classify(type) %>);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -7,13 +7,13 @@ import { Component, OnInit<% if(!!viewEncapsulation) { %>, ViewEncapsulation<% }
<%= dasherize(name) %> works!
</p>
`,<% } else { %>
templateUrl: './<%= dasherize(name) %>.component.html',<% } if(inlineStyle) { %>
templateUrl: './<%= dasherize(name) %>.<%= dasherize(type) %>.html',<% } if(inlineStyle) { %>
styles: []<% } else { %>
styleUrls: ['./<%= dasherize(name) %>.component.<%= style %>']<% } %><% if(!!viewEncapsulation) { %>,
styleUrls: ['./<%= dasherize(name) %>.<%= dasherize(type) %>.<%= style %>']<% } %><% if(!!viewEncapsulation) { %>,
encapsulation: ViewEncapsulation.<%= viewEncapsulation %><% } if (changeDetection !== 'Default') { %>,
changeDetection: ChangeDetectionStrategy.<%= changeDetection %><% } %>
})
export class <%= classify(name) %>Component implements OnInit {
export class <%= classify(name) %><%= classify(type) %> implements OnInit {
constructor() { }

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { <%= classify(name) %>Component } from './<%= dasherize(name) %>.component';
describe('<%= classify(name) %>Component', () => {
let component: <%= classify(name) %>Component;
let fixture: ComponentFixture<<%= classify(name) %>Component>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ <%= classify(name) %>Component ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(<%= classify(name) %>Component);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -49,15 +49,18 @@ function addDeclarationToNgModule(options: ComponentOptions): Rule {
return host;
}
options.type = !!options.type ? options.type : 'Component';
const modulePath = options.module;
const source = readIntoSourceFile(host, modulePath);
const componentPath = `/${options.path}/`
+ (options.flat ? '' : strings.dasherize(options.name) + '/')
+ strings.dasherize(options.name)
+ '.component';
+ '.'
+ strings.dasherize(options.type);
const relativePath = buildRelativePath(modulePath, componentPath);
const classifiedName = strings.classify(`${options.name}Component`);
const classifiedName = strings.classify(options.name) + strings.classify(options.type);
const declarationChanges = addDeclarationToModule(source,
modulePath,
classifiedName,
@ -77,7 +80,7 @@ function addDeclarationToNgModule(options: ComponentOptions): Rule {
const exportRecorder = host.beginUpdate(modulePath);
const exportChanges = addExportToModule(source, modulePath,
strings.classify(`${options.name}Component`),
strings.classify(options.name) + strings.classify(options.type),
relativePath);
for (const change of exportChanges) {
@ -95,7 +98,7 @@ function addDeclarationToNgModule(options: ComponentOptions): Rule {
const entryComponentRecorder = host.beginUpdate(modulePath);
const entryComponentChanges = addEntryComponentToModule(
source, modulePath,
strings.classify(`${options.name}Component`),
strings.classify(options.name) + strings.classify(options.type),
relativePath);
for (const change of entryComponentChanges) {

View File

@ -24,6 +24,7 @@ describe('Component Schematic', () => {
inlineTemplate: false,
changeDetection: ChangeDetection.Default,
style: Style.Css,
type: 'Component',
skipTests: false,
module: undefined,
export: false,
@ -256,6 +257,17 @@ describe('Component Schematic', () => {
expect(tree.files).not.toContain('/projects/bar/src/app/foo/foo.component.css');
});
it('should respect the type option', async () => {
const options = { ...defaultOptions, type: 'Route' };
const tree = await schematicRunner.runSchematicAsync('component', options, appTree).toPromise();
const content = tree.readContent('/projects/bar/src/app/foo/foo.route.ts');
const testContent = tree.readContent('/projects/bar/src/app/foo/foo.route.spec.ts');
expect(content).toContain('export class FooRoute implements OnInit');
expect(testContent).toContain('describe(\'FooRoute\'');
expect(tree.files).toContain('/projects/bar/src/app/foo/foo.route.css');
expect(tree.files).toContain('/projects/bar/src/app/foo/foo.route.html');
});
it('should use the module flag even if the module is a routing module', async () => {
const routingFileName = 'app-routing.module.ts';
const routingModulePath = `/projects/bar/src/app/${routingFileName}`;

View File

@ -88,6 +88,11 @@
],
"x-user-analytics": 5
},
"type": {
"type": "string",
"description": "Adds a developer-defined type to the filename, in the format \"name.type.ts\".",
"default": "Component"
},
"spec": {
"type": "boolean",
"description": "When true (the default), generates a \"spec.ts\" test file for the new component.",