Search code examples
javascriptangularangular-materialangular-cli

How Can I Make Custom Tabs Using Angular Materials Tabs?


I want to use Angular Material library and build my own library with some custom designs. But facing some problems while splitting the material components. I think the problem is with shadow DOM. Here is the code that i want to achieve.

Code

custom-tabs-group.html -parent

<div class="custom-tabs">
  <mat-tab-group disableRipple>
    <ng-content></ng-content>
  </mat-tab-group>
</div>

custom-tabs.html -child

<custom-tabs-group [tabContent]="tabContent">
  <mat-tab *ngFor="let tab of tabContent" label="{{tab.title}}">{{tab.content}} </mat-tab>
</custom-tabs-group>

is it even possible? Please let me know


Solution

  • Actually i figured it out with some hack i don't know if its a good approch or not

    custom-tabs.component.html

    <div class="custom-tabs">
      <mat-tab-group disableRipple>
        <mat-tab *ngFor="let tab of tabsContentList" label="{{tab.label}}">
          <div [innerHTML]="tab.htmlContent"></div>
        </mat-tab>
      </mat-tab-group>
    </div>
    

    custom-tabs-component.ts

    import { DomSanitizer } from '@angular/platform-browser';
    import { Component, OnInit, ViewEncapsulation, AfterContentInit, ContentChildren, Input, ViewChild, ElementRef, QueryList } from '@angular/core';
    
    
    @Component({
      selector: 'il-tabs-content',
      template: `
          <div #content>
             <ng-content></ng-content>
           </div>
           `
      ,
    })
    export class TabsContentComponent implements OnInit {
      @Input() label: String;
      @ViewChild('content') set content(content: ElementRef) {
        console.log("block three", content)
        this.htmlContent = content;
        if (this.htmlContent) {
          this.htmlContent = this.htmlContent.nativeElement.innerHTML;
        }
      }
    
      htmlContent: any;
      constructor() { }
      ngOnInit() {
      }
    
    }
    
    @Component({
      selector: 'il-tabs-group',
      templateUrl: './tabs.component.html',
      styleUrls: ['./tabs.component.css'],
      encapsulation: ViewEncapsulation.None
    })
    export class TabsGroupComponent implements OnInit, AfterContentInit {
      @ContentChildren(TabsContentComponent) tabsContentList: QueryList<TabsContentComponent>;
    
      constructor(public sanitizer: DomSanitizer) { }
    
      ngOnInit() {
    
      }
      ngAfterContentInit() {
        this.tabsContentList.forEach((tabInstance) => {
          var sanEle = this.sanitizer.bypassSecurityTrustHtml(tabInstance.htmlContent)
          tabInstance.htmlContent = sanEle;
          return tabInstance
        })
      }
    }
    
    

    usage

      <il-tabs-group>
        <il-tabs-content label="hello-1">
          <h1>hello-1 content</h1>
        </il-tabs-content>
        <il-tabs-content label="hello-2">
          <h1>hello-2 content</h1>
        </il-tabs-content>
        <il-tabs-content label="hello-3">
          <h1>hello-3 content</h1>
          <h2>extra content</h2>
        </il-tabs-content>
      </il-tabs-group>
    

    i defined two components 'il-tabs-content' and 'li-tabs-group'. with this now i can use my own custom tabs build over angular material tabing with dynamic tabs. Anyone with better approch are welcome to share their ideas. thanks