3

I want to create a dynamic tabs loader using angular 2 material this is the syntax which I want to support

<generic-tabs [tabs]="tabs" tabVisibleField="name">
            <test-cmp [tabContent] testData="hello"></test-cmp>
            <test-cmp [tabContent] testData="hello from cmp one"></test-cmp>
            <test-cmp [tabContent] testData="hello from cmp 2"></test-cmp></generic-tabs>

And inside the component I want to render tabs using material design and bind to each tab a component which contains tabContent This is the template for generic tabs

<md-tab-group *ngIf="componentsReferences && componentsReferences.length > 0">
    <md-tab *ngFor="let componentRef of componentsReferences; let i=index" (click)="onTabClick($event, i)">
        <template md-tab-label>{{getDisplayField(i)}}</template>

        <template md-tab-content>
            //inject the component for this tab
        </template>
    </md-tab>
</md-tab-group>

What I don't know is how to select all the component which are are inside the generic-tabs tag and make angular to create them

3
  • this is what I tried to do until now but if didn't work. On rc-06 I get create embededView is not a function plnkr.co/edit/TdLZghoOstRqcItmrJg3?p=preview Commented Oct 7, 2016 at 12:02
  • This is the error I get on rc-0.6 for something similar with that plunk browser_adapter.ts:82 ORIGINAL EXCEPTION: TypeError: Cannot read property 'createEmbeddedView' of null Commented Oct 7, 2016 at 12:04
  • browser_adapter.ts:82 TypeError: Cannot read property 'createEmbeddedView' of null at ViewContainerRef_.createEmbeddedView (core.umd.js:8344) at ViewContainerRef_.createEmbeddedView (core.umd.js:8344) at NgTemplateOutlet.ngOnChanges (common.umd.js:1236) at DebugAppView._View_GenericTabsComponent5.detectChangesInternal (GenericTabsComponent.ngfactory.js:369) at DebugAppView.AppView.detectChanges (core.umd.js:12586) at DebugAppView.detectChanges (core.umd.js:12691) Commented Oct 7, 2016 at 12:05

1 Answer 1

4

I found the solution using multiple content transclusion

<md-tab-group *ngIf="tabsContentComponents" [selectedIndex]="selectedIndex" (selectChange)="onTabClick($event)">
    <md-tab *ngFor="let componentRef of tabsContentComponents; let i=index">
        <template md-tab-label>
            <tab-header [tabHeader]="tabHeaders[i]"> </tab-header>
        </template>        
        <template md-tab-content *ngIf="componentRef">
            <template [ngTemplateOutlet]="componentRef"></template>
        </template>
    </md-tab>
</md-tab-group>

@Component({
    moduleId: module.id,
    selector: 'generic-tabs',
    templateUrl: 'generic-tabs.html',
    encapsulation: ViewEncapsulation.None,
    styleUrls: [
        './generic-tabs.css'
    ]
})
export class GenericTabsComponent implements AfterViewInit {
    @Input() tabHeaders: Array<TabHeaderModel>;
    @Input() selectedIndex: number = 0;
    @Input()
    set tabErrors(errors: Array<ITabError>) {
        for (let e of errors) {
            this.setTabError(e);
        }
    }

    @Input()
    set resetErrorIndex(tabIndex: number) {
        if (tabIndex < 0 || tabIndex >= this.tabErrors.length) {
            return;
        }

        this.setTabError({ tabIndex, errorColor: "", errorIcon: "", errorsCount: 0 });
    }

    @ContentChildren(TemplateRef) tabsContentTemplateRef: QueryList<TemplateRef<any>>;
    @Output() onTabChange: EventEmitter<ITabChangeEvent> = new EventEmitter<ITabChangeEvent>();

    private tabsContentComponents: Array<any> = [];

    ngAfterViewInit() {
        this.mapTabs();
        this.tabsContentTemplateRef.changes.subscribe(this.remapTabs.bind(this));
    }

    remapTabs() {
        this.tabsContentComponents = [];
        this.mapTabs();
    }

    mapTabs() {
        this.tabsContentTemplateRef.map(t => {
            this.tabsContentComponents.push(t);
        });
    }

    onTabClick($event) {
        this.selectedIndex = $event.index;
        this.onTabChange.emit({ $event, selectedTab: this.tabHeaders[this.selectedIndex], selectedTabIndex: this.selectedIndex});
    }

    private setTabError(e: ITabError) {
        this.tabHeaders[e.tabIndex].errorsCount = e.errorsCount;
        this.tabHeaders[e.tabIndex].errorsIcon = e.errorIcon;
        this.tabHeaders[e.tabIndex].errorsIconColor = e.errorIcon;
    }
}

Using this component I can use the tabs to render specific component's in their content.

<generic-tabs *ngIf="selectedItem && formRef && formRef.editMode" [tabHeaders]="tabHeaders" (onTabChange)="log($event)">
                <template>
                    <data-grid>
                    </data-grid>
                </template>
                <template>
                    Pay Types
                </template>
                <template>
                    <shift-calendar></shift-calendar>
                </template>
                <template>
                    <holiday-calendar></holiday-calendar>
                </template>
            </generic-tabs>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.