File
Implements
Metadata
selector |
sort-options |
styleUrls |
./sort-options.component.scss |
templateUrl |
./sort-options.component.html |
Index
Properties
|
|
Methods
|
|
Inputs
|
|
Outputs
|
|
useFilters
|
Default value : true
|
|
Outputs
view
|
Type : EventEmitter<string>
|
|
Methods
Public
hasView
|
hasView(view)
|
|
|
Public
openFilters
|
openFilters()
|
|
|
Public
selectSorting
|
selectSorting(index)
|
|
Perform a search with a selected sort option
|
Public
selectUnit
|
selectUnit(index)
|
|
Change unit to metric or imperial
|
Public
selectView
|
selectView(view)
|
|
|
displayedSorts
|
Type : []
|
Default value : []
|
|
viewMode
|
Type : "GRID" | "LIST" | "TABLE"
|
|
import { Component, OnInit, Input, Output, SimpleChanges, OnChanges, EventEmitter } from '@angular/core';
import { LabelService } from 'src/app/core/services/label-service/label-service.service';
import { LoadingIndicatorService } from 'src/app/core/services/loading-indicator.service';
import { FilterToggleService } from 'src/app/core/services/filter-toggler/filter-toggle.service';
import { ConstantsService } from 'src/app/shared/constants/constants.service';
export interface SortData {
systems: any;
sortOptions: any;
tableAvailable?: boolean;
}
@Component({
selector: 'sort-options',
templateUrl: './sort-options.component.html',
styleUrls: ['./sort-options.component.scss']
})
export class SortOptionsComponent implements OnInit, OnChanges {
@Input() data: SortData;
@Input() viewOptions; // If possible to switch between grid and list or table view. Input list of view options.
@Input() useFilters = true;
@Input() id: string;
@Output() view: EventEmitter<string> = new EventEmitter<string>();
viewMode: 'GRID' | 'LIST' | 'TABLE';
sortMode: string;
displayedSorts = [];
unitMode: string;
// Labels
filterLabel: string;
sortByLabel: string;
constructor(
private labelService: LabelService,
private loadingService: LoadingIndicatorService,
private filterToggleService: FilterToggleService,
private constants: ConstantsService
) {}
ngOnInit() {
this.labelService.getLabel('filterSortingMobile').then(res => this.filterLabel = res );
this.labelService.getLabel('filterSorting').then(res => this.sortByLabel = res );
this.viewMode = this.viewOptions ? this.viewOptions[0] : 'GRID';
const preferedUnit = localStorage.getItem(this.constants.MEASUREMENT_SYSTEM_CACHE_KEY);
if (preferedUnit) {
const unit = JSON.parse(preferedUnit);
this.selectUnit(unit);
}
}
ngOnChanges(changes: SimpleChanges): void {
// If going up a level while on table view, switch to grid view.
if (changes.data.previousValue && changes.data.previousValue.tableAvailable && !changes.data.currentValue.tableAvailable) {
this.selectView('GRID');
}
if (changes && this.data) {
this.displayedSorts = []; // Reset for each change
if (this.data.sortOptions) {
// Find selected sorting option and set sortMode to it.
this.data.sortOptions.forEach(sort => {
if (sort.selected) {
this.labelService.getLabel(sort.displayName).then(res => this.sortMode = res.toLowerCase());
}
// Filter out sort options that should be displayed if applicable
if (sort.properties && sort.properties.showInDropDown) {
this.displayedSorts.push(sort);
}
});
// If no sort options with properties existed, show default options
if (this.displayedSorts.length === 0) { this.displayedSorts = this.data.sortOptions; }
// Get labels for sorting options
this.displayedSorts.forEach(sort => {
this.labelService.getLabel(sort.displayName).then(res => sort.displayName = res);
});
}
if (this.data.systems) {
// Find selected system unit
this.data.systems.forEach(unit => {
if (unit.selected) {
this.unitMode = unit.displayName;
}
});
}
}
}
public hasView(view): boolean {
return this.viewOptions.includes(view);
}
/** Switch to selected view */
public selectView(view): void {
this.viewMode = view;
this.view.emit(view);
}
/** Perform a search with a selected sort option */
public selectSorting(index) {
this.loadingService.show();
this.displayedSorts[index].select();
this.labelService.getLabel(this.displayedSorts[index].displayName).then(res => this.sortMode = res.toLowerCase());
}
/** Change unit to metric or imperial */
public selectUnit(index) {
this.loadingService.show();
this.data.systems[index].select();
this.unitMode = this.data.systems[index].displayName;
localStorage.setItem(this.constants.MEASUREMENT_SYSTEM_CACHE_KEY, JSON.stringify(index));
}
public openFilters() {
this.filterToggleService.showFilters(this.id);
}
}
<div class="toolbelt-options">
<div class="view-mode" >
<div class="btn-group" role="group" *ngIf="viewOptions?.length > 0">
<div class="view-button" [ngClass]="{'selected': viewMode=='GRID'}" (click)="selectView('GRID')" *ngIf="hasView('GRID')">
<i class="fas fa-th" ></i>
</div>
<div class="view-button" [ngClass]="{'selected': viewMode=='LIST'}" (click)="selectView('LIST')" *ngIf="hasView('LIST')">
<i class="fas fa-list"></i>
</div>
<div class="view-button" [ngClass]="{'selected': viewMode=='TABLE'}" (click)="selectView('TABLE')" [hidden]="!data?.tableAvailable" *ngIf="hasView('TABLE')">
<i class="fas fa-list"></i>
</div>
</div>
</div>
<div class="filters">
<div class="filter-toggle" (click)="openFilters()" *ngIf="useFilters">
<i class="fas fa-filter"></i>.
<span class="filter-toggler">{{ filterLabel }}</span>
</div>
<div class="systems-radio" *ngIf="data.systems?.length > 0">
<label class="radio-inline" *ngFor="let system of data.systems; let i=index" [ngClass]="{'active': system.selected}"
(click)="selectUnit(i)">
<i class="far fa-circle" *ngIf="!system.selected"></i>
<i class="far fa-dot-circle" *ngIf="system.selected"></i>
<span>{{system.displayName}}</span>
</label>
</div>
<div class="sort-select" *ngIf="data.sortOptions?.length > 0" placement="bottom-right" ngbDropdown>
<div class="sort-toggle" id="sortSelect" ngbDropdownToggle>
{{ sortByLabel }}
<span class="sort-mode" [innerHTML]="sortMode"></span>
</div>
<div ngbDropdownMenu aria-labelledby="sortSelect">
<button class="dropdown-item" *ngFor="let sort of displayedSorts; let i=index" (click)="selectSorting(i)">
<span [innerHTML]="sort.displayName"></span>
</button>
</div>
</div>
</div>
</div>
@import "src/app/styles/helpers";
//@import "~bootstrap/scss/dropdown";
:host {
width: 100%;
}
.toolbelt-options {
display: flex;
align-items: flex-end;
justify-content: space-between;
@include media-breakpoint-up(md) {
align-items: center;
}
.view-mode {
color: #495A63;
.view-button {
position: relative;
display: inline-block;
border: 1px solid #e2e2e2;
background-color: #f8f8f8;
color: #808080;
padding: calc-rem(3) calc-rem(5);
cursor: pointer;
i {
@include font-size(20);
}
}
.selected {
background-color: white;
color: $blue;
}
}
.filters {
display: flex;
flex-direction: column;
text-align: right;
@include media-breakpoint-up(md) {
flex-direction: row;
}
.filter-toggle {
cursor: pointer;
i {
vertical-align: middle;
color: $blue;
}
.filter-toggler {
@include media-breakpoint-up(md) {
margin-right: calc-rem(15);
}
}
@include media-breakpoint-up(lg) {
display: none;
}
}
.systems-radio {
display: flex;
user-select: none;
align-items: center;
@include media-breakpoint-up(md) {
margin-right: calc-rem(20);
}
.radio-inline {
margin-right: calc-rem(10);
display: inline-block;
margin-bottom: 0;
cursor: pointer;
user-select: none;
&:hover {
color: $dark-blue;
}
&:last-child {
margin: 0;
}
&.active {
color: $blue;
}
i {
@include font-size(17);
margin-right: calc-rem(5);
}
}
}
.sort-select {
.sort-toggle {
cursor: pointer;
.sort-mode { font-weight: 600; }
}
.dropdown-menu {
padding: 0;
background-color: $cool-grey;
.dropdown-item {
padding: calc-rem(8) calc-rem(24);
@include font-size(14);
color: white;
&:hover {
background-color: $cool-grey;
color: $light-blue;
cursor: pointer;
}
}
}
}
}
}
Legend
Html element with directive