fix(examples): form-field custom control example not working (#13043)

* Removes a workaround that allowed the secondary component of the form-field-custom-control to use the primary asset files (`form-field-custom-control-example.(html|css` are reserved for the primary example component). This workaround caused the example to not render properly inside of StackBlitz.
* Fixes that the build-example-module task does not properly detect stylesheet additional files.
* Depends on https://github.com/angular/material.angular.io/pull/516
Fixes #13021
This commit is contained in:
Paul Gschwendtner
2018-09-12 00:15:37 +02:00
committed by Jeremy Elbourn
parent c5076bab74
commit 4f58d5a424
6 changed files with 63 additions and 50 deletions
@@ -1,21 +1 @@
div {
display: flex;
}
input {
border: none;
background: none;
padding: 0;
outline: none;
font: inherit;
text-align: center;
}
span {
opacity: 0;
transition: opacity 200ms;
}
:host.floating span {
opacity: 1;
}
/** No CSS for this example */
@@ -1,7 +1,5 @@
<div [formGroup]="parts">
<input class="area" formControlName="area" size="3">
<span>&ndash;</span>
<input class="exchange" formControlName="exchange" size="3">
<span>&ndash;</span>
<input class="subscriber" formControlName="subscriber" size="4">
</div>
<mat-form-field>
<my-tel-input placeholder="Phone number" required></my-tel-input>
<mat-icon matSuffix>phone</mat-icon>
<mat-hint>Include area code</mat-hint>
</mat-form-field>
@@ -5,17 +5,24 @@ import {FormBuilder, FormGroup} from '@angular/forms';
import {MatFormFieldControl} from '@angular/material';
import {Subject} from 'rxjs';
/** @title Form field with custom telephone number input control. */
@Component({
selector: 'form-field-custom-control-example',
templateUrl: 'form-field-custom-control-example.html',
styleUrls: ['form-field-custom-control-example.css'],
})
export class FormFieldCustomControlExample {}
/** Data structure for holding telephone number. */
export class MyTel {
constructor(public area: string, public exchange: string, public subscriber: string) {}
}
/** Custom `MatFormFieldControl` for telephone number input. */
@Component({
selector: 'my-tel-input',
templateUrl: 'form-field-custom-control-example.html',
styleUrls: ['form-field-custom-control-example.css'],
templateUrl: 'my-tel-input-example.html',
styleUrls: ['my-tel-input-example.css'],
providers: [{provide: MatFormFieldControl, useExisting: MyTelInput}],
host: {
'[class.floating]': 'shouldLabelFloat',
@@ -109,17 +116,3 @@ export class MyTelInput implements MatFormFieldControl<MyTel>, OnDestroy {
}
}
}
/** @title Form field with custom telephone number input control. */
@Component({
selector: 'form-field-custom-control-example',
template: `
<mat-form-field>
<my-tel-input placeholder="Phone number" required></my-tel-input>
<mat-icon matSuffix>phone</mat-icon>
<mat-hint>Include area code</mat-hint>
</mat-form-field>
`
})
export class FormFieldCustomControlExample {}
@@ -0,0 +1,21 @@
.my-tel-input-container {
display: flex;
}
.my-tel-input-element {
border: none;
background: none;
padding: 0;
outline: none;
font: inherit;
text-align: center;
}
.my-tel-input-spacer {
opacity: 0;
transition: opacity 200ms;
}
:host.floating .my-tel-input-spacer {
opacity: 1;
}
@@ -0,0 +1,7 @@
<div [formGroup]="parts" class="my-tel-input-container">
<input class="my-tel-input-element" formControlName="area" size="3">
<span class="my-tel-input-spacer">&ndash;</span>
<input class="my-tel-input-element" formControlName="exchange" size="3">
<span class="my-tel-input-spacer">&ndash;</span>
<input class="my-tel-input-element" formControlName="subscriber" size="4">
</div>
+19 -5
View File
@@ -22,6 +22,7 @@ interface ParsedMetadata {
component: string;
title: string;
templateUrl: string;
styleUrls: string[];
}
interface ParsedMetadataResults {
@@ -172,9 +173,16 @@ function parseExampleMetadata(fileName: string, sourceContent: string): ParsedMe
if (decorator.expression.expression.text === 'Component') {
for (const arg of decorator.expression.arguments) {
for (const prop of arg.properties) {
const name = prop.name.text;
const value = prop.initializer.text;
meta[name] = value;
const propName = prop.name.text;
// Since additional files can be also stylesheets, we need to properly parse
// the styleUrls metadata property.
if (propName === 'styleUrls' && ts.isArrayLiteralExpression(prop.initializer)) {
meta[propName] = prop.initializer.elements
.map((literal: ts.StringLiteral) => literal.text);
} else {
meta[propName] = prop.initializer.text;
}
}
}
@@ -204,8 +212,8 @@ task('build-examples-module', () => {
for (const sourcePath of matchedFiles) {
const sourceContent = fs.readFileSync(sourcePath, 'utf-8');
const { primaryComponent, secondaryComponents } =
parseExampleMetadata(sourcePath, sourceContent);
const {primaryComponent, secondaryComponents} =
parseExampleMetadata(sourcePath, sourceContent);
if (primaryComponent) {
// Generate a unique id for the component by converting the class name to dash-case.
@@ -226,9 +234,15 @@ task('build-examples-module', () => {
for (const meta of secondaryComponents) {
example.additionalComponents.push(meta.component);
if (meta.templateUrl) {
example.additionalFiles.push(meta.templateUrl);
}
if (meta.styleUrls) {
example.additionalFiles.push(...meta.styleUrls);
}
example.selectorName.push(meta.component);
}
}