File
Implements
Metadata
selector |
app-search |
styleUrls |
search.component.css |
templateUrl |
./search.component.html |
Methods
filterByCategory
|
filterByCategory(category: Category)
|
|
|
onSearchInputChange
|
onSearchInputChange(query: string)
|
|
Parameters :
Name |
Type |
Optional |
query |
string
|
no
|
|
onSearchInputClear
|
onSearchInputClear()
|
|
|
onSortOptionChange
|
onSortOptionChange(changeEvent: MatButtonToggleChange)
|
|
Parameters :
Name |
Type |
Optional |
changeEvent |
MatButtonToggleChange
|
no
|
|
openSnackBar
|
openSnackBar()
|
|
|
applicationsCount
|
applicationsCount: number
|
Type : number
|
Default value : 0
|
|
hitsPerPage
|
hitsPerPage: number
|
Type : number
|
Default value : 20
|
|
isInfiniteScrollRequested
|
isInfiniteScrollRequested: boolean
|
Type : boolean
|
|
An internal flag used when an infinite scroll has be initiated.
|
lastResultCount
|
lastResultCount:
|
Default value : Infinity
|
|
Keep track of the previous count (number of hits).
|
searchCategories
|
searchCategories: Category[]
|
Type : Category[]
|
|
The categories (facets) computed for each search result.
|
sortOption
|
sortOption: string
|
Type : string
|
Default value : 'rating_desc'
|
|
Accessors
applications
|
getapplications()
|
|
setapplications(value: [])
|
|
Reseting the state of the "appliations" property will automatically clear the list of the categories
reset the scroll behavior and reset the last count.
Parameters :
Name |
Type |
Optional |
value |
[]
|
no
|
|
import { Component, OnInit, AfterContentInit } from '@angular/core';
import { Observable, PartialObserver, Subject } from 'rxjs';
import { filter, switchMap, share, switchMapTo } from 'rxjs/operators';
import { MatSnackBar, MatButtonToggleChange } from '@angular/material';
import { AlgoliaService } from '@app/core/algolia/algolia.service';
import { Category } from '../facets/category/category.component';
import { SearchService, Application } from './../search.service';
@Component({
selector: 'app-search',
templateUrl: './search.component.html',
styleUrls: ['./search.component.css']
})
export class SearchComponent implements OnInit {
hitsPerPage = 20;
applicationsCount = 0;
sortOption = 'rating_desc';
private _applications: Application[];
/**
* Reseting the state of the "appliations" property will automatically clear the list of the categories
* reset the scroll behavior and reset the last count.
*
*/
set applications(value: Application[]) {
if (!value || value.length === 0) {
// reset the component local state
this.searchCategories = [];
this.isInfiniteScrollRequested = false;
this.lastResultCount = Infinity;
}
this._applications = value;
}
get applications() {
return this._applications;
}
/**
* The categories (facets) computed for each search result.
*/
searchCategories: Category[];
/**
* An internal flag used when an infinite scroll has be initiated.
*/
isInfiniteScrollRequested: boolean;
/**
* Keep track of the previous count (number of hits).
*/
lastResultCount = Infinity;
constructor(private search: AlgoliaService, private snackBar: MatSnackBar) {
this.applications = [];
this.searchCategories = [];
this.search.setQueryParameter({
hitsPerPage: this.hitsPerPage
});
}
ngOnInit() {
const handleResultSubscription = content => {
this.applicationsCount = content.nbHits;
const categoriesFacet = content.getFacetValues('category') as any[];
if (categoriesFacet.length > 1) {
this.searchCategories = categoriesFacet;
}
this.lastResultCount = content.hits.length;
if (this.isInfiniteScrollRequested) {
this.applications = this.applications.concat(content.hits);
} else {
this.applications = content.hits;
}
this.isInfiniteScrollRequested = false;
};
this.search.searchState.result$.subscribe(handleResultSubscription);
this.search.searchState.error$.subscribe(content => {
this.applications = [];
});
this.search.searchState.search$.subscribe(content => {
if (this.isInfiniteScrollRequested) {
this.openSnackBar();
}
});
this.search.searchState.change$.subscribe(content => {});
}
onSearchInputChange(query: string) {
this.search.sortByRatingDesc(query);
}
filterByCategory(category: Category) {
this.search.toggleFacetRefinement({
name: 'category',
query: category.name
});
}
onSearchInputClear() {
this.applications = [];
}
onScroll() {
if (this.lastResultCount >= this.hitsPerPage && this.applications.length > 0) {
this.isInfiniteScrollRequested = true;
this.search.nextPage();
}
}
openSnackBar() {
this.snackBar.open('Loading more content...', '', {
duration: 500
});
}
onSortOptionChange(changeEvent: MatButtonToggleChange) {
switch (changeEvent.value) {
case 'rating_desc':
this.search.sortByRatingDesc();
break;
case 'price_asc':
this.search.sortByPriceAsc();
break;
case 'relevance_desc':
default:
this.search.sortByRelevance();
}
}
}
<mat-card class="card" appInfiniteScroll (scroll)="onScroll()">
<mat-card-header>
<a class="card_algolia-credits" href="https://www.algolia.com/product" target="__blank" aria-label="Powered by Algolia">
<p>Powered by</p>
</a>
<app-search-input class="card_search-input" (clear)="onSearchInputClear()" (query)="onSearchInputChange($event)"></app-search-input>
</mat-card-header>
<mat-card-content class="card_content" [class.no-result]="applications.length === 0">
<div class="card_sorting-options">
<mat-button-toggle-group (change)="onSortOptionChange($event)" #group="matButtonToggleGroup" *ngIf="applications.length > 0">
<mat-button-toggle [checked]="sortOption" value="relevance_desc">
Most Relevant
</mat-button-toggle>
<mat-button-toggle [checked]="sortOption" value="price_asc">
Lowest Price
</mat-button-toggle>
<mat-button-toggle [checked]="sortOption" value="rating_desc">
Most Popular
</mat-button-toggle>
</mat-button-toggle-group>
</div>
<mat-expansion-panel *ngIf="searchCategories.length > 0">
<mat-expansion-panel-header>
<mat-panel-title>
Categories
</mat-panel-title>
</mat-expansion-panel-header>
<app-category (selectionChanged)="filterByCategory($event)" [categories]="searchCategories"></app-category>
</mat-expansion-panel>
<app-search-result *ngIf="applications.length > 0" [entries]="applications"></app-search-result>
</mat-card-content>
</mat-card>
<router-outlet></router-outlet>
Legend
Html element with directive