File

src/modules/generic-search/classes/abstract-search-component.ts

Description

Abstract class defining the common properties and methods for the Search Page using the StarkGenericSearchComponent.

Extends

AbstractStarkFormComponent

Implements

OnInit OnDestroy

Index

Properties
Methods
Accessors

Constructor

Public constructor(genericSearchService: StarkGenericSearchService<SearchResultsType | CriteriaType>, logger: StarkLoggingService, progressService: StarkProgressIndicatorService)

Class constructor

Parameters :
Name Type Optional Description
genericSearchService StarkGenericSearchService<SearchResultsType | CriteriaType> No
  • Service implementing the StarkGenericSearchService interface providing all the necessary methods to search items.
logger StarkLoggingService No
  • The StarkLoggingService instance of the application.
progressService StarkProgressIndicatorService No
  • Service that provides an easy way to change the visibility of a progress indicator.

Methods

Protected emitResult
emitResult(result: SearchResultsType[])

Emit the latest results and optionally keeps a reference to them if the preserveLatestResults option is enabled.

Parameters :
Name Type Optional Description
result SearchResultsType[] No
  • Result to emit
Returns : void
Public ngOnDestroy
ngOnDestroy()

Component lifecycle hook

Returns : void
Public ngOnInit
ngOnInit()

Component lifecycle hook

Returns : void
Public onNew
onNew()

Invoke the genericSearchService.createNew() method

Returns : void
Public onReset
onReset(form: UntypedFormGroup)

Invoke the genericSearchService.resetSearchState() method and clears the results

Parameters :
Name Type Optional Description
form UntypedFormGroup No
  • Form to reset
Returns : void
Public onSearch
onSearch(formGroup: UntypedFormGroup)

Invoke the search passing the formGroup's working copy only if the Search formGroup is valid

Parameters :
Name Type Optional Description
formGroup UntypedFormGroup No
  • The 'search' formGroup
Returns : void
Public performSearch
performSearch(searchCriteria: CriteriaType)

Invoke the genericSearchService.search() method and emits the results. If no searchCriteria object is passed, then the current form's working copy is used.

Parameters :
Name Type Optional Default value Description
searchCriteria CriteriaType No this.workingCopy
  • Criteria to be used to perform the search
Returns : void
Protected showProgress
showProgress(show: boolean)

Call the progressService show/hide methods in case there is a progressTopic defined

Parameters :
Name Type Optional Description
show boolean No
  • Whether to show the progress indicator or not
Returns : void
Public updateWorkingCopy
updateWorkingCopy(searchCriteria: CriteriaType)

Update the current working copy of the searchCriteria

Parameters :
Name Type Optional Description
searchCriteria CriteriaType No
  • New value of searchCriteria
Returns : void
Protected isDirty
isDirty()

Check whether the working copy is exactly the same as the original copy. Performs a deep comparison between the two objects to determine if they are equivalent.

Returns : boolean
Protected reset
reset()

Revert the form's working copy back to the original copy (a deep clone copy)

Returns : void
Protected setOriginalCopy
setOriginalCopy(originalCopy: CriteriaType)

Set the form's original copy to the object passed as parameter (a deep cloned copy).

Default: {} (empty object)

Parameters :
Name Type Optional Default value Description
originalCopy CriteriaType No <any>{}
  • The object to be set as the form's original copy
Returns : void

Properties

Protected performSearchOnInit
Type : boolean

Whether a new search should be performed automatically after initialization in case the last search criteria can be fetched from the application state (@ngrx/store)

Protected preserveLatestResults
Type : boolean

Whether the latest emitted results by the emitResult() method will be kept in the latestResults variable

Public progressIndicatorConfig
Type : StarkProgressIndicatorConfig

The config of the progress indicator to be shown/hidden when performing the search.

Public results$
Type : ReplaySubject<SearchResultsType[]>

Observable that will emit the search results. This Observable is created as soon as the Search Page controller is constructed and the first value it emits is an empty array in order to avoid the having undefined values passed down to the subscriber(s).

Public logger
Type : StarkLoggingService
- The `StarkLoggingService` instance of the application.
Public originalCopy
Type : CriteriaType

The form's original copy (the initial model when the form is pristine)

Public workingCopy
Type : CriteriaType

The form's working copy (the current model with the latest changes)

Accessors

latestResults
getlatestResults()

The latest search results that have been emitted in the results$ Observable.

Returns : Readonly | undefined
import { ReplaySubject, Subscription } from "rxjs";
import { map, take } from "rxjs/operators";
import { Directive, OnDestroy, OnInit } from "@angular/core";
import { UntypedFormGroup } from "@angular/forms";
import { AbstractStarkFormComponent } from "./abstract-form-component";
import { StarkGenericSearchService } from "./generic-search.service.intf";
import { StarkSearchState } from "../entities";
import { StarkErrorImpl, StarkLoggingService } from "@nationalbankbelgium/stark-core";
import { StarkFormUtil } from "@nationalbankbelgium/stark-ui/src/util";
import {
	StarkProgressIndicatorConfig,
	StarkProgressIndicatorType,
	StarkProgressIndicatorService
} from "@nationalbankbelgium/stark-ui/src/modules/progress-indicator";

/**
 * Default progress indicator configuration
 */
const defaultProgressIndicatorConfig: StarkProgressIndicatorConfig = {
	topic: "",
	type: StarkProgressIndicatorType.SPINNER
};

/**
 * Abstract class defining the common properties and methods for the Search Page using the {@link StarkGenericSearchComponent}.
 */
@Directive({})
// eslint-disable-next-line @angular-eslint/directive-class-suffix
export abstract class AbstractStarkSearchComponent<SearchResultsType, CriteriaType>
	extends AbstractStarkFormComponent<CriteriaType>
	implements OnInit, OnDestroy
{
	/**
	 * @internal
	 * @ignore
	 */
	private _latestResults?: Readonly<SearchResultsType[]>;
	/**
	 * @internal
	 * @ignore
	 */
	private searchStateSubscription!: Subscription;

	/**
	 * Whether a new search should be performed automatically after initialization in case the last search criteria can be fetched
	 * from the application state (@ngrx/store)
	 */
	protected performSearchOnInit: boolean;
	/**
	 * Whether the latest emitted results by the emitResult() method will be kept in the latestResults variable
	 */
	protected preserveLatestResults: boolean;
	/**
	 * The config of the progress indicator to be shown/hidden when performing the search.
	 */
	public progressIndicatorConfig: StarkProgressIndicatorConfig;
	/**
	 * Observable that will emit the search results. This Observable is created as soon as the Search Page controller is constructed
	 * and the first value it emits is an empty array in order to avoid the having undefined values passed down to the subscriber(s).
	 */
	public results$!: ReplaySubject<SearchResultsType[]>;

	/**
	 * Class constructor
	 * @param genericSearchService - Service implementing the StarkGenericSearchService interface providing all the necessary methods to search items.
	 * @param logger - The `StarkLoggingService` instance of the application.
	 * @param progressService - Service that provides an easy way to change the visibility of a progress indicator.
	 */
	public constructor(
		protected genericSearchService: StarkGenericSearchService<SearchResultsType, CriteriaType>,
		logger: StarkLoggingService,
		protected progressService: StarkProgressIndicatorService
	) {
		super(logger);

		this.progressIndicatorConfig = defaultProgressIndicatorConfig;
		this.performSearchOnInit = true;
		this.preserveLatestResults = false;
	}

	/**
	 * Component lifecycle hook
	 */
	public ngOnInit(): void {
		// it will re-emit the latest value whenever a new observer subscribes to it
		// so an empty array can be emitted as the result$ initial value (to avoid having undefined results)
		this.results$ = new ReplaySubject<SearchResultsType[]>(1);
		// initially an empty array is emitted
		this.emitResult([]);

		// if a search was done previously (saved in the Redux state)
		// then the search is automatically performed on initialization (only if the performSearchOnInit option is TRUE)
		this.searchStateSubscription = this.genericSearchService
			.getSearchState()
			.pipe(
				map((searchState: StarkSearchState<CriteriaType>) => {
					if (searchState.hasBeenSearched && this.performSearchOnInit) {
						this.performSearch(searchState.criteria);
					}
					return searchState.criteria;
				})
			)
			.subscribe((searchCriteria: CriteriaType) => {
				this.setOriginalCopy(searchCriteria);
			});
	}

	/**
	 * Component lifecycle hook
	 */
	public ngOnDestroy(): void {
		this.searchStateSubscription.unsubscribe();
	}

	/**
	 * Invoke the search passing the formGroup's working copy only if the Search formGroup is valid
	 * @param formGroup - The 'search' formGroup
	 */
	public onSearch(formGroup: UntypedFormGroup): void {
		if (StarkFormUtil.isFormGroupValid(formGroup)) {
			this.performSearch(this.workingCopy);
		}
	}

	/**
	 * Invoke the genericSearchService.createNew() method
	 */
	public onNew(): void {
		if (typeof this.genericSearchService.createNew !== "undefined") {
			this.genericSearchService.createNew();
		} else {
			throw new StarkErrorImpl(
				'AbstractStarkSearchComponent: When StarkGenericSearch component has the "new" button defined, ' +
					'the service must have an implementation for "createNew" method.'
			);
		}
	}

	/**
	 * Invoke the genericSearchService.resetSearchState() method and clears the results
	 * @param form - Form to reset
	 */
	public onReset(form: UntypedFormGroup): void {
		this.genericSearchService.resetSearchState();
		StarkFormUtil.setFormChildControlsState(form, ["untouched", "pristine"]);
		StarkFormUtil.setFormGroupState(form, ["untouched", "pristine"]);
		this.emitResult([]);
	}

	/**
	 * Update the current working copy of the searchCriteria
	 * @param searchCriteria - New value of searchCriteria
	 */
	public updateWorkingCopy(searchCriteria: CriteriaType): void {
		this.workingCopy = searchCriteria;
	}

	/**
	 * Invoke the genericSearchService.search() method and emits the results. If no searchCriteria object is passed, then the current
	 * form's working copy is used.
	 * @param searchCriteria - Criteria to be used to perform the search
	 */
	public performSearch(searchCriteria: CriteriaType = this.workingCopy): void {
		this.performSearchOnInit = false; // prevent further automatic searches due to the subscription to StarkSearchState changes in NgOnInit

		this.showProgress(true);

		this.genericSearchService
			.search(searchCriteria)
			.pipe(
				take(1) // this ensures that the observable will be automatically unsubscribed after emitting the value
			)
			.subscribe(
				(result: SearchResultsType[]) => {
					this.emitResult(result);
					this.showProgress(false);
				},
				() => {
					// hide the progress in case of error
					this.showProgress(false);
				}
			);
	}

	/**
	 * The latest search results that have been emitted in the results$ Observable.
	 */
	public get latestResults(): Readonly<SearchResultsType[]> | undefined {
		return this._latestResults;
	}

	/**
	 * Call the progressService show/hide methods in case there is a progressTopic defined
	 * @param show - Whether to show the progress indicator or not
	 */
	protected showProgress(show: boolean): void {
		if (this.progressIndicatorConfig && this.progressIndicatorConfig.topic && this.progressIndicatorConfig.topic !== "") {
			if (show) {
				this.progressService.show(this.progressIndicatorConfig.topic);
			} else {
				this.progressService.hide(this.progressIndicatorConfig.topic);
			}
		}
	}

	/**
	 * Emit the latest results and optionally keeps a reference to them if the preserveLatestResults option is enabled.
	 * @param result - Result to emit
	 */
	protected emitResult(result: SearchResultsType[]): void {
		if (this.preserveLatestResults) {
			this._latestResults = result;
		}
		this.results$.next(result);
	}
}

results matching ""

    No results matching ""