angular/aio/src/app/custom-elements/code/code-tabs.component.ts
JoostK cd7b199219 feat(ivy): check regular attributes that correspond with directive inputs (#33066)
Prior to this change, a static attribute that corresponds with a
directive's input would not be type-checked against the type of the
input. This is unfortunate, as a static value always has type `string`,
whereas the directive's input type might be something different. This
typically occurs when a developer forgets to enclose the attribute name
in brackets to make it a property binding.

This commit lets static attributes be considered as bindings with string
values, so that they will be properly type-checked.

PR Close #33066
2019-10-14 20:25:20 +00:00

85 lines
2.7 KiB
TypeScript

/* tslint:disable component-selector */
import { AfterViewInit, Component, ElementRef, Input, OnInit, QueryList, ViewChild, ViewChildren } from '@angular/core';
import { CodeComponent } from './code.component';
export interface TabInfo {
class: string;
code: string;
path: string;
region: string;
header?: string;
language?: string;
linenums?: string;
}
/**
* Renders a set of tab group of code snippets.
*
* The innerHTML of the `<code-tabs>` component should contain `<code-pane>` elements.
* Each `<code-pane>` has the same interface as the embedded `<code-example>` component.
* The optional `linenums` attribute is the default `linenums` for each code pane.
*/
@Component({
selector: 'code-tabs',
template: `
<!-- Use content projection so that the provided HTML's code-panes can be split into tabs -->
<div #content style="display: none"><ng-content></ng-content></div>
<mat-card>
<mat-tab-group class="code-tab-group" [disableRipple]="true">
<mat-tab style="overflow-y: hidden;" *ngFor="let tab of tabs">
<ng-template mat-tab-label>
<span class="{{ tab.class }}">{{ tab.header }}</span>
</ng-template>
<aio-code class="{{ tab.class }}"
[language]="tab.language"
[linenums]="tab.linenums"
[path]="tab.path"
[region]="tab.region"
[header]="tab.header">
</aio-code>
</mat-tab>
</mat-tab-group>
</mat-card>
`,
})
export class CodeTabsComponent implements OnInit, AfterViewInit {
tabs: TabInfo[];
@Input() linenums: string | undefined;
@ViewChild('content', { static: true }) content: ElementRef<HTMLDivElement>;
@ViewChildren(CodeComponent) codeComponents: QueryList<CodeComponent>;
ngOnInit() {
this.tabs = [];
const codeExamples = Array.from(this.content.nativeElement.querySelectorAll('code-pane'));
for (const tabContent of codeExamples) {
this.tabs.push(this.getTabInfo(tabContent));
}
}
ngAfterViewInit() {
this.codeComponents.toArray().forEach((codeComponent, i) => {
codeComponent.code = this.tabs[i].code;
});
}
/** Gets the extracted TabInfo data from the provided code-pane element. */
private getTabInfo(tabContent: Element): TabInfo {
return {
class: tabContent.getAttribute('class') || '',
code: tabContent.innerHTML,
path: tabContent.getAttribute('path') || '',
region: tabContent.getAttribute('region') || '',
header: tabContent.getAttribute('header') || undefined,
language: tabContent.getAttribute('language') || undefined,
linenums: tabContent.getAttribute('linenums') || this.linenums,
};
}
}