Skip to content

Instantly share code, notes, and snippets.

@ntorrey
Last active April 30, 2022 18:50
Show Gist options
  • Save ntorrey/9bc7459febe54b9083caa12053283f31 to your computer and use it in GitHub Desktop.
Save ntorrey/9bc7459febe54b9083caa12053283f31 to your computer and use it in GitHub Desktop.
Tab Swiper Component (Ionic/Angular)
// Full-sized Tab (Segment) Swiper Component for use in Ionic/Angular Apps.
// The only dependency that you need besides Ionic and Angular is Swiper.js.
// It's not a super-fancy component. It's simply an <ion-segment> component linked to a <swiper> component.
// When you swipe to a different page, the segment on top will update and vice-versa.
// The component makes use of <ion-content> internally, so don't place this component inside an <ion-content> element
// Don't forget to import the tab-swiper.module.ts
// Implementation in your component
<app-tab-swiper selectedTab="Slide 1">
<ng-template tab-slide title="Slide 1">
<div>Slide 1 content</div>
</ng-template>
<ng-template tab-slide title="Slide 2">
<div>Slide 2 content</div>
</ng-template>
<ng-template tab-slide title="Slide 3">
<div>Slide 3 content</div>
</ng-template>
<ng-template tab-slide title="Slide 4">
<div>Slide 4 content</div>
</ng-template>
</app-tab-swiper>
<ng-template #template>
<ion-segment [value]="selectedTab">
<ion-segment-button
*ngFor="let segment of segments"
[value]="segment"
(click)="slideToPage(getIndex(segment))">
{{ segment}}
</ion-segment-button>
</ion-segment>
<ion-content>
<swiper (realIndexChange)="updateSegment($event)" (swiper)="setSwiperInstance($event)">
<ng-template swiperSlide *ngFor="let slide of slides">
<ng-template [ngTemplateOutlet]="slide.template"></ng-template>
</ng-template>
</swiper>
</ion-content>
</ng-template>
// These are both necessary in order to allow for vertical scrolling.
// Only works if View Encapsulation is set to None.
swiper {
height: 100%;
width: 100%;
}
.swiper-slide {
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
import {
AfterViewInit,
Component,
ContentChildren, Directive,
Input,
OnInit, QueryList, TemplateRef,
ViewChild,
ViewContainerRef
} from '@angular/core';
import { Swiper } from 'swiper';
import { IonSegment } from '@ionic/angular';
@Directive({
selector: '[tab-slide]',
})
export class TabSwiperSlideDirective {
@Input() title = ''
constructor(public template: TemplateRef<any>) {
}
}
@Component({
selector: 'app-tab-swiper',
templateUrl: './tab-swiper.component.html',
styleUrls: ['./tab-swiper.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class TabSwiperComponent implements OnInit, AfterViewInit {
@Input() segments = ['One', 'Two', 'Three']
@Input() selectedTab = 'One'
@ViewChild('template') template;
@ViewChild(IonSegment) segment: IonSegment;
@ContentChildren(TabSwiperSlideDirective) slideElements: QueryList<TabSwiperSlideDirective>
slides: TabSwiperSlideDirective[];
swiper: Swiper
constructor(private viewContainerRef: ViewContainerRef) { }
ngOnInit() {}
ngAfterViewInit() {
this.viewContainerRef.createEmbeddedView(this.template)
this.slides = this.slideElements.toArray()
let arr = []
this.slides.forEach(slide =>
arr.push(slide.title)
)
this.segments = arr
}
setSwiperInstance(swiper: any) {
this.swiper = swiper;
}
updateSegment(ev: [swiper: Swiper]) {
const index = ev[0].activeIndex
this.segment.value = this.segments[index]
}
slideToPage(page: number) {
this.swiper.slideTo(page)
}
getIndex(pageName: string): number {
return this.segments.findIndex(segment => segment === pageName)
}
}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IonicModule } from '@ionic/angular';
import { TabSwiperComponent, TabSwiperSlideDirective } from './tab-swiper.component';
import { SwiperModule } from 'swiper/angular';
@NgModule({
imports: [
CommonModule,
IonicModule,
SwiperModule
],
declarations: [TabSwiperComponent, TabSwiperSlideDirective],
exports: [TabSwiperComponent, TabSwiperSlideDirective]
})
export class TabSwiperModule {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment