Ionic - Horizontal scroll tab for Categories [duplicate]
Event though this questions may be considered as a duplicate of another question, I'll still add this answer because I think there's a better way to handle the categories (at least, from the UI/UX point of view).
The end result would look like this:
Basically, we're using the Ionic slider component to show the categories, but showing up to 3 categories per slide.
View:
In the view we just need to add a toolbar with a row, that will include 3 columns inside: one for the left arrow, another one for the slider, and the last one for the right arrow. Please also notice that we're setting the slidesPerView="3"
property in the ion-slides
element.
<ion-header>
<ion-navbar color="primary">
<button ion-button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>App Name</ion-title>
</ion-navbar>
<ion-toolbar>
<ion-row class="filters">
<ion-col class="col-with-arrow" (click)="slidePrev()" no-padding col-1>
<ion-icon *ngIf="showLeftButton" name="arrow-back"></ion-icon>
</ion-col>
<ion-col no-padding col-10>
<ion-slides (ionSlideDidChange)="slideChanged()" slidesPerView="3">
<ion-slide (click)="filterData(category.id)" *ngFor="let category of categories">
<p [class.selected]="selectedCategory?.id === category.id">{{ category.name }}</p>
</ion-slide>
</ion-slides>
</ion-col>
<ion-col class="col-with-arrow" (click)="slideNext()" no-padding col-1>
<ion-icon *ngIf="showRightButton" name="arrow-forward"></ion-icon>
</ion-col>
</ion-row>
</ion-toolbar>
</ion-header>
Component code:
Then we just need to handle what to do when any category is selected, or when the current slide changes:
// Angular
import { Component, Injector, ViewChild } from '@angular/core';
// Ionic
import { IonicPage, Slides } from 'ionic-angular';
// Models
import { CategoryModel } from './../../models/category.model';
@Component({ ... })
export class HomePage {
@ViewChild(Slides) slides: Slides;
public selectedCategory: CategoryModel;
public categories: Array<CategoryModel>;
public showLeftButton: boolean;
public showRightButton: boolean;
constructor(public injector: Injector) { ... }
// ...
private initializeCategories(): void {
// Select it by defaut
this.selectedCategory = this.categories[0];
// Check which arrows should be shown
this.showLeftButton = false;
this.showRightButton = this.categories.length > 3;
}
public filterData(categoryId: number): void {
// Handle what to do when a category is selected
}
// Method executed when the slides are changed
public slideChanged(): void {
let currentIndex = this.slides.getActiveIndex();
this.showLeftButton = currentIndex !== 0;
this.showRightButton = currentIndex !== Math.ceil(this.slides.length() / 3);
}
// Method that shows the next slide
public slideNext(): void {
this.slides.slideNext();
}
// Method that shows the previous slide
public slidePrev(): void {
this.slides.slidePrev();
}
}
Styles:
.filters {
ion-col {
text-align: center;
font-size: 1.6rem;
line-height: 1.6rem;
ion-icon {
color: #ccc;
}
&.col-with-arrow {
display: flex;
justify-content: center;
align-items: center;
}
}
p {
color: #fff;
margin: 0;
font-size: 1.6rem;
line-height: 1.6rem;
}
.selected {
font-weight: 700;
}
}