File

app/sitesearch/shared/facet-range/facet-range.component.ts

Implements

OnInit OnChanges

Metadata

selector range-facet
styleUrls ./facet-range.component.scss
templateUrl ./facet-range.component.html

Index

Properties
Methods
Inputs

Constructor

constructor(loadingService: LoadingIndicatorService, modalService: NgbModal, labelService: LabelService, idGenerator: IdGeneratorService)
Parameters :
Name Type Optional
loadingService LoadingIndicatorService No
modalService NgbModal No
labelService LabelService No
idGenerator IdGeneratorService No

Inputs

facet

Methods

Public applyExactFilter
applyExactFilter()
Returns : void
Public applyFilter
applyFilter()

Applies selected range filter by doing a search to the SearchService

Returns : void
Public exactUpdate
exactUpdate()

Updates exact input to correct boundary

Returns : void
Public maxUpdate
maxUpdate()

Updates max input to make sure it stays in the right boundary. Called each time the input is blurred.

Returns : void
Public minUpdate
minUpdate()

Updates min input to make sure it stays in the right boundary. Called each time the input is blurred.

Returns : void
ngOnChanges
ngOnChanges(changes: SimpleChanges)
Parameters :
Name Type Optional
changes SimpleChanges No
Returns : void
ngOnInit
ngOnInit()
Returns : void
Public openModal
openModal(content)
Parameters :
Name Optional
content No
Returns : void
Public switchFilter
switchFilter(filter)
Parameters :
Name Optional
filter No
Returns : void
Public toggle
toggle()

Toggle facet

Returns : void

Properties

applyLabel
Type : string
editLabel
Type : string
exactFilterLabel
Type : string
exactInput
Type : FormControl
Default value : new FormControl()
facetId
Default value : this.idGenerator.getId()
facetName
Type : string
Public labelService
Type : LabelService
Public loadingService
Type : LoadingIndicatorService
max
maxInput
Type : FormControl
Default value : new FormControl()
min
minInput
Type : FormControl
Default value : new FormControl()
Public modalService
Type : NgbModal
open
Default value : true
rangerFilterLabel
Type : string
import { Component, OnInit, Input, SimpleChanges, OnChanges } from '@angular/core';
import { FormControl } from '@angular/forms';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { LabelService } from 'src/app/core/services/label-service/label-service.service';
import { LoadingIndicatorService } from 'src/app/core/services/loading-indicator.service';
import { IdGeneratorService } from 'src/app/core/services/id-generator.service';

@Component({
	selector: 'range-facet',
	templateUrl: './facet-range.component.html',
	styleUrls: ['./facet-range.component.scss']
})
export class RangeFacetComponent implements OnInit, OnChanges {

	@Input() facet;

	open = true;
	minInput: FormControl = new FormControl();
	maxInput: FormControl = new FormControl();
	exactInput: FormControl = new FormControl();
	min;
	max;

	facetId = this.idGenerator.getId();	// Id for the accordion

	// Labels
	facetName: string;
	editLabel: string;
	exactFilterLabel: string;
	rangerFilterLabel: string;
	applyLabel: string;

	constructor(
		public loadingService: LoadingIndicatorService,
		public modalService: NgbModal,
		public labelService: LabelService,
		private idGenerator: IdGeneratorService
	) {}

	ngOnInit() {
		this.labelService.getLabel(this.facet.displayName).then(res => this.facetName = res);
		this.labelService.getLabel('facetRangeEditRange').then(res => this.editLabel = res);
		this.labelService.getLabel('facetRangeExactFilter').then(res => this.exactFilterLabel = res);
		this.labelService.getLabel('facetRangeRangeFilter').then(res => this.rangerFilterLabel = res);
		this.labelService.getLabel('facetsApplyRange').then(res => this.applyLabel = res);
	}

	ngOnChanges(changes: SimpleChanges): void {
		if (changes) {
			// Make sure that input values are in range of min and max values
			this.min = this.facet.properties.min;
			this.max = this.facet.properties.max;
			// If a range search has been made, set the input to the selected values.
			if (this.facet.properties.selectedLower && this.facet.properties.selectedUpper) {
				if (this.facet.properties.selectedLower >= this.min) { this.minInput.setValue(this.facet.properties.selectedLower); }
				else { this.minInput.setValue(this.min); }

				if (this.facet.properties.selectedUpper <= this.max) { this.maxInput.setValue(this.facet.properties.selectedUpper); }
				else { this.maxInput.setValue(this.max); }
			}
			else if (this.facet.properties.selectExact) {
				this.minInput.setValue(this.facet.properties.selectExact);
				this.maxInput.setValue(this.facet.properties.selectExact);
			}
			else {
				this.minInput.setValue(this.min);
				this.maxInput.setValue(this.max);
			}

		}
	}

	/** Updates min input to make sure it stays in the right boundary. Called each time the input is blurred. */
	public minUpdate() {
		// Input can not be less than the minimum value of the search results.
		if (this.minInput.value < this.facet.properties.min) {
			this.minInput.setValue(this.facet.properties.min);
		}
		// Min input can not be larger than the max input and not larger than the maximum value of the search results.
		if (this.minInput.value > this.maxInput.value || this.minInput.value > this.facet.properties.max) {
			this.minInput.setValue(this.maxInput.value);
		}
	}

	/** Updates max input to make sure it stays in the right boundary. Called each time the input is blurred. */
	public maxUpdate() {
		if (this.maxInput.value > this.facet.properties.max) {
			this.maxInput.setValue(this.facet.properties.max);
		}
		if (this.maxInput.value < this.minInput.value || this.maxInput.value < this.facet.properties.min) {
			this.maxInput.setValue(this.minInput.value);
		}
	}

	/** Updates exact input to correct boundary */
	public exactUpdate() {
		if (this.exactInput.value < this.facet.properties.min) {
			this.exactInput.setValue(this.facet.properties.min);
		} else if (this.exactInput.value > this.facet.properties.max) {
			this.exactInput.setValue(this.facet.properties.max);
		}
	}

	/** Toggle facet */
	public toggle() {
		this.open = !this.open;
	}

	/** Applies selected range filter by doing a search to the SearchService */
	public applyFilter() {
		// Make sure input values are correct
		this.minUpdate();
		this.maxUpdate();

		this.loadingService.show();

		if (this.minInput.value === this.maxInput.value) {
			// When min and max have are the same, do an exact search.
			this.facet.selectExact(parseFloat(this.minInput.value));
		} else {
			// When min and max are different, search for a range.
			this.facet.selectRange({
				min: parseFloat(this.minInput.value),
				max: parseFloat(this.maxInput.value)
			});
		}

		this.modalService.dismissAll();
	}

	public applyExactFilter() {
		this.loadingService.show();
		this.facet.selectRange({
			min: parseFloat(this.exactInput.value),
			max: parseFloat(this.exactInput.value)
		});
		this.modalService.dismissAll();
	}

	public switchFilter(filter) {
		this.modalService.dismissAll();
		this.modalService.open(filter, {size: 'sm', centered: true});
	}

	public openModal(content) {
		this.modalService.open(content, {size: 'sm', centered: true});
	}
}
<div class="facet-range">
    <div class="accordion" [id]="'range-facet' + facetId">
        <div class="card">
            <div class="card-header" [id]="facetName">
                <a class="toggler" data-toggle="collapse" [href]="'#range-' + facetId" role="button" aria-expanded="true" [attr.aria-controls]="'range' + facetId">
                    <div>
                        <span class="mr-2">{{facetName | uppercase}}</span>
                        <span [innerHTML]="'['+ facet.properties.symbol + ']'">[]</span>
                    </div>
                    <i class="closed icon-chevronUp"></i>
                    <i class="open icon-chevronDown"></i>
                </a>
            </div>
            <div class="collapse show" [id]="'range-' + facetId" [attr.aria-labelledby]="facetName" [attr.data-parent]="'#range-facet' + facetId">
                <div class="card-body range-info">
                    <div class="current-range">
                        <span>{{ facet.properties.selectedLower || min }}</span>
                        <span>-</span>
                        <span>{{ facet.properties.selectedUpper || max }} {{facet.properties.unit}}</span>
                    </div>
            
                    <span class="edit-range" (click)="openModal(range)">{{ editLabel | uppercase }}</span>
                </div>
            </div>
        </div>
    </div>

    <ng-template #range let-modal>
        <div class="modal-header">
            <h4 class="modal-title">{{facetName}}</h4>
            <button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
                <span aria-hidden="true">&times;</span>
            </button>
        </div>
        <div class="modal-body">
            <input ngbAutofocus type="number" class="range-input" [formControl]="minInput" (blur)="minUpdate()" (keyup.enter)="applyFilter()">
            <p>-</p>
            <input type="number" class="range-input" [formControl]="maxInput" (blur)="maxUpdate()" (keyup.enter)="applyFilter()">
        </div>
        <div class="modal-footer">
            <p (click)="switchFilter(exact)">{{exactFilterLabel}} <i class="icon-chevronLarge-next"></i></p>
            <div class="apply-filter" (click)="applyFilter()">{{applyLabel | uppercase}}</div>
        </div>
    </ng-template>

    <ng-template #exact let-modal>
        <div class="modal-header">
            <h4 class="modal-title">{{facetName}}</h4>
            <button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
                <span aria-hidden="true">&times;</span>
            </button>
        </div>
        <div class="modal-body">
            <input ngbAutofocus type="number" class="range-input" [formControl]="exactInput" (blur)="minUpdate()" (keyup.enter)="applyExactFilter()">
        </div>
        <div class="modal-footer">
            <p (click)="switchFilter(range)">{{rangerFilterLabel}} <i class="icon-chevronLarge-next"></i></p>
            <div class="apply-filter" (click)="applyExactFilter()">{{applyLabel | uppercase}}</div>
        </div>
    </ng-template>

</div>

./facet-range.component.scss

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

.facet-range {
    margin-bottom: calc-rem(2);
    color: white;
    background-color: $cool-grey;
    
    .card {
        background-color: inherit;
        border: none;

        &-header {
            border: none;
            background: transparent;
            padding: calc-rem(20);

            .toggler {
                display: flex;
                justify-content: space-between;
                align-items: center;
                color: $light-blue;
                @include font-scale(14, uppercase);
                letter-spacing: calc-rem(2);

                &:hover { text-decoration: none; }

                i { @include font-size(8); }

                &[aria-expanded=true] .open {
                    display: none;
                }
                &[aria-expanded=false] .closed {
                    display: none;
                }
            }
        }

        &-body {
            padding-top: calc-rem(10);
            
            &.range-info {
                color: white;
                display: flex;
                flex-direction: row;
                justify-content: space-between;
        
                .current-range {
                    span {
                        margin-right: calc-rem(5);
                    }
                }
        
                .edit-range {
                    color: $light-blue;
                    cursor: pointer;
                    @include font-size(14);
                    letter-spacing: calc-rem(0.4);
                }
            }
        }
    }
}

::ng-deep .modal-content {
    z-index: 9999;
}

::ng-deep .modal-body {
    display: flex;
    flex-direction: column;

    .range-input {
        -moz-appearance: textfield;
        
        &::-webkit-outer-spin-button,
        &::-webkit-inner-spin-button {
            -webkit-appearance: none;
            margin: 0;
        }
    }

    p { text-align: center; }
}

::ng-deep .modal-footer {
    display: flex;
    flex-direction: column;

    p {
        cursor: pointer;

        &:hover {
            color: $cool-grey;
        }
    }

    .apply-filter {
        padding: 10px 0;
        width: 100%;
        text-align: center;
        color: white;
        background-color: $green;
        cursor: pointer;
    }
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""