File

app/dxa/dxa-entity/views/tab-views/tab-main/tab-main.component.ts

Implements

OnInit OnDestroy

Metadata

selector div[tab-main]
styleUrls ./tab-main.component.scss
templateUrl ./tab-main.component.html

Index

Properties
Methods
Inputs

Constructor

constructor(rowResolver: RowResolverService, constants: ConstantsService, idService: IdGeneratorService, util: UtilService, activatedRoute: ActivatedRoute, resize: ResizeContentService)
Parameters :
Name Type Optional
rowResolver RowResolverService No
constants ConstantsService No
idService IdGeneratorService No
util UtilService No
activatedRoute ActivatedRoute No
resize ResizeContentService No

Inputs

entity

Methods

ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
onResize
onResize()
Returns : void
parseJson
parseJson(jsonData: any)
Parameters :
Name Type Optional
jsonData any No
Returns : TabRow
parseTab
parseTab(rawTabJson: any)
Parameters :
Name Type Optional
rawTabJson any No
Returns : Tab
setActiveTab
setActiveTab(tabRow: TabRow, index: number)
Parameters :
Name Type Optional
tabRow TabRow No
index number No
Returns : void
tabClick
tabClick(index)
Parameters :
Name Optional
index No
Returns : void

Properties

Public constants
Type : ConstantsService
data
Type : TabRow
id
Type : string
Default value : this.idService.getId()
Public idService
Type : IdGeneratorService
inDesktop
Type : boolean
Public resize
Type : ResizeContentService
Public rowResolver
Type : RowResolverService
Public util
Type : UtilService
import { Component, OnInit, Input, OnDestroy, HostBinding } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { RowResolverService } from 'src/app/core/services/row-resolver.service';
import { UtilService } from 'src/app/core/services/util-service/util.service';
import { ConstantsService } from 'src/app/shared/constants/constants.service';
import { IdGeneratorService } from 'src/app/core/services/id-generator.service';
import { ResizeContentService } from 'src/app/core/services/resize-service/resize-content.service';

interface Tab {
	Id: string; // Used by the shortcuts component as a scroll target
	Title: string;
	Content: any[];
	ContentIds: string[];
}

interface TabRow {
	activeTab: Tab;
	activeIndex: number;
	tabs: Tab[];
	tabIdToActivate: string;
}

@Component({
	selector: 'div[tab-main]',
	templateUrl: './tab-main.component.html',
	styleUrls: ['./tab-main.component.scss'],
})
export class TabMainComponent implements OnInit, OnDestroy {

	@Input() entity;
	data: TabRow;
	id: string = this.idService.getId();
	inDesktop: boolean;

	constructor(public rowResolver: RowResolverService,
				// Constants is used in the html template
				public constants: ConstantsService,
				public idService: IdGeneratorService,
				public util: UtilService,
				private activatedRoute: ActivatedRoute,
				public resize: ResizeContentService) { }

	ngOnInit() {
		this.data = this.parseJson(this.entity);
		this.resize.registerCallback(this.id, e => this.onResize());
		// Call it here so that the inDesktop get's its proper value without the need to resize the browser
		this.onResize();
	}

	ngOnDestroy(): void {
		this.resize.destroyCallback(this.id);
	}

	onResize() {
		const currentWidth = window.innerWidth;
		this.inDesktop = currentWidth >= this.constants.BOOTSTRAP_BREAKPOINTS.MD;
	}

	parseJson(jsonData: any): TabRow {
		const itemId = (this.activatedRoute.snapshot.fragment || '');
		const allRawTabs: any[] = this.util.extract(jsonData, 'Entities' ) || [];
		const tabs = allRawTabs.map(rawTab => this.parseTab(rawTab));

		const tab = // try find a tab with the tab nested component-id or tab id specified in the url
				tabs.find(t => t.Id.includes(itemId)) ||
				tabs.find(t => t.ContentIds.includes(itemId));

		const tabIdToActivate = tab !== undefined ? tab.Id : '';
		const tabRow: TabRow = {
			activeTab: tabs[0],
			activeIndex: 0,
			tabs: tabs,
			tabIdToActivate: tabIdToActivate
		};
		return tabRow;
	}

	parseTab(rawTabJson: any): Tab {
		const tabTitle: string = this.util.extract(rawTabJson, 'TabTitle');
		// Apply to row transformer since the template expects this format (this is the same that is used for regions)
		const entities = this.util.extract(rawTabJson, 'TabContnetEntities');
		const entitiesGroupedAsRows = this.rowResolver.transform(entities, 'MAIN');
		const id = this.util.extract(rawTabJson, 'Id');
		 // Add ids for all entities present in all tabs
		const contentIds: string[] = entities.map(e => {
			if(e.Id !== undefined){
				return e.Id.includes('-') ? `${this.constants.COMPONENT_ID_PREFIX}-${e.Id.split('-')[0]}` : `${this.constants.COMPONENT_ID_PREFIX}-${e.Id}`;
			}
		});
		// Entities that don't have Id are arrays and need further processing
		entities.forEach(e => {
			if(e.Id === undefined && e.Entities !== undefined){
				contentIds.push(e.Entities.map(ee => {
					if(ee.Id !== undefined){
						return ee.Id.includes('-') ? `${this.constants.COMPONENT_ID_PREFIX}-${ee.Id.split('-')[0]}` : `${this.constants.COMPONENT_ID_PREFIX}-${ee.Id}`;
					}
				}));
			}
		});
		const tab: Tab = {
			Id: `${this.constants.COMPONENT_ID_PREFIX}-${id}`,
			Title: tabTitle,
			Content: entitiesGroupedAsRows,
			ContentIds: contentIds
		};

		return tab;
	}

	setActiveTab(tabRow: TabRow, index: number): void {
		const newActive = tabRow.tabs[index];
		tabRow.activeIndex = index;
		tabRow.activeTab = newActive;
	}

	tabClick(index): void {
		this.setActiveTab(this.data, index);
	}

}
<!-- Desktop -->
<ngb-tabset class="tab-desktop" justify="start" *ngIf="inDesktop" [activeId]="data.tabIdToActivate">
  <ngb-tab [id]="tab.Id" [title]="tab.Title" *ngFor="let tab of data.tabs">
    <ng-template ngbTabContent>
      <ng-container *ngFor="let row of tab?.Content">
          <div dxa-entity [entities]="row" [region]="'MAIN'"></div>
      </ng-container>
    </ng-template>
  </ngb-tab>
</ngb-tabset>

<!-- Mobile -->
<div class="tab-mobile">
  <div ngbDropdown *ngIf="!inDesktop">
    <div ngbDropdownToggle [id]="'dropdown-' + id">
      <span>{{data?.activeTab.Title}}</span>
      <i class="icon-chevronDown"> </i>
      <i class="icon-chevronUp"> </i>
    </div>
    <div ngbDropdownMenu [attr.aria-labelledby]="'dropdown-' + id">
      <div class="menu-item" [id]="tab.Id" [ngClass]="{'active-menu-item': i === data.activeIndex}" (click)="tabClick(i)" ngbDropdownItem *ngFor="let tab of data.tabs; let i = index">
        <div class="container">
          {{tab.Title}}
        </div>
      </div>
    </div>
  </div>
  <div class="tab-content" *ngIf="!inDesktop">
    <ng-container *ngFor="let row of data?.activeTab?.Content">
      <div dxa-entity [entities]="row" [region]="'MAIN'"></div>
    </ng-container>
  </div>
</div>



./tab-main.component.scss

@import "src/app/styles/helpers";

:host {
    @include media-breakpoint-up(md) {
        background-color: $light-green;
    }
}

// Desktop
::ng-deep .tab-desktop {
    .nav {
        background-color: $light-green;
        color: $cool-grey;
        border: none;
        display: flex;
        @include make-container();
        @include make-container-max-widths();

        &-link {
            padding: calc-rem(20) calc-rem(50);
            @include font-scale(14, uppercase);
            letter-spacing: calc-rem(0.4);
        }
        &-item {
            text-align: center;
            .nav-link.active {
                border-color: $light-green;
                // TODO Find a better solution for checking the background color
                ::ng-deep .support-page & {
                    background-color: $light-slate;
                }
            }
            .nav-link {
                text-transform: uppercase;
                border: none;
                border-top: calc-rem(2) solid $light-green;
                &:hover {
                    border-color: $light-green;
                }
            }
            a {
                color: $cool-grey;
                border: none;
            }
        }
    }
}

::ng-deep .tab-content {
    background-color: white;
}


// Mobile
.tab-mobile {
    ::ng-deep .dropdown {
        display: flex;
        min-height: calc-rem(75);
        background-color: $light-green;
        @include font-scale(14, uppercase);
        letter-spacing: calc-rem(0.4);
        cursor: pointer;

        &-toggle {
            @include make-container();
            @include make-container-max-widths();
            display: flex;
            justify-content: space-between;
            align-self: stretch;
            align-items: center;
            text-transform: uppercase;

            &[aria-expanded=true] .icon-chevronDown {
                display: none;
            }

            &[aria-expanded=false] .icon-chevronUp {
                display: none;
            }

            &::after {
                content: none;
            }

            i {
                margin-right: calc-rem(10);
            }
        }

        &-menu {
            border: 1px solid $light-green;
            background-color: $light-green;
            width: 100%;
            left: 0 !important;
            padding: 0;

            .menu-item {
                cursor: pointer;
                padding: calc-rem(15) 0;
                background-color: $light-green;
                @include font-scale(14, uppercase);
                letter-spacing: calc-rem(0.4);

                &:hover {
                    background-color: $white;
                }

                &.active-menu-item {
                    font-weight: bold;
                }
            }
        }
    }
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""