OpenSlides/client/src/app/shared/components/search-value-selector/search-value-selector.component.ts

167 lines
4.3 KiB
TypeScript
Raw Normal View History

import { Component, Input, ViewChild, OnDestroy } from '@angular/core';
import { FormControl } from '@angular/forms';
import { MatSelect } from '@angular/material';
import { BehaviorSubject, Subscription } from 'rxjs';
import { auditTime } from 'rxjs/operators';
import { TranslateService } from '@ngx-translate/core';
import { Selectable } from '../selectable';
/**
* Reusable Searchable Value Selector
*
* Use `multiple="true"`, `[InputListValues]=myValues`,`[formControl]="myformcontrol"`, `[form]="myform_name"` and `placeholder={{listname}}` to pass the Values and Listname
*
* ## Examples:
*
* ### Usage of the selector:
*
* ngDefaultControl: https://stackoverflow.com/a/39053470
*
* ```html
* <os-search-value-selector
* ngDefaultControl
2018-09-19 15:18:57 +02:00
* [multiple]="true"
* placeholder="Placeholder"
* [InputListValues]="myListValues"
* [formControl]="myformcontrol">
* </os-search-value-selector>
* ```
*
*/
@Component({
selector: 'os-search-value-selector',
templateUrl: './search-value-selector.component.html',
styleUrls: ['./search-value-selector.component.scss']
})
export class SearchValueSelectorComponent implements OnDestroy {
/**
* Saves the current subscription to _inputListSubject.
*/
private _inputListSubscription: Subscription = null;
/**
* Value of the search input
*/
private searchValue = '';
/**
* All items
*/
private selectableItems: Selectable[];
/**
* Decide if this should be a single or multi-select-field
*/
@Input()
public multiple = false;
/**
* Decide, if none should be included, if multiple is false.
*/
@Input()
public includeNone = false;
/**
* Boolean, whether the component should be rendered with full width.
*/
@Input()
public fullWidth = false;
/**
* The inputlist subject. Subscribes to it and updates the selector, if the subject
* changes its values.
*/
@Input()
public set InputListValues(value: BehaviorSubject<Selectable[]>) {
if (!value) {
return;
}
// unsubscribe to old subscription.
if (this._inputListSubscription) {
this._inputListSubscription.unsubscribe();
}
// this.inputSubject = value;
this._inputListSubscription = value.pipe(auditTime(10)).subscribe(items => {
this.selectableItems = items;
if (this.formControl) {
items.length === 0
? this.formControl.disable({ emitEvent: false })
: this.formControl.enable({ emitEvent: false });
}
});
}
/**
* Placeholder of the List
*/
@Input()
public listname: String;
/**
* Name of the Form
*/
@Input()
public formControl: FormControl;
/**
* The MultiSelect Component
*/
@ViewChild('thisSelector', { static: true })
public thisSelector: MatSelect;
/**
* Empty constructor
*/
2019-03-11 09:48:20 +01:00
public constructor(protected translate: TranslateService) {}
/**
* Unsubscribe on destroing.
*/
public ngOnDestroy(): void {
if (this._inputListSubscription) {
this._inputListSubscription.unsubscribe();
}
}
/**
* Function to get a list filtered by the entered search value.
*
* @returns The filtered list of items.
*/
public getFilteredItems(): Selectable[] {
if (this.selectableItems) {
return this.selectableItems.filter(item => {
const idString = '' + item.id;
const foundId =
idString
.trim()
.toLowerCase()
.indexOf(this.searchValue) !== -1;
if (foundId) {
return true;
}
return (
item
.toString()
.toLowerCase()
.indexOf(this.searchValue) > -1
);
});
}
}
/**
* Function to set the search value.
*
* @param searchValue the new value the user is searching for.
*/
public onSearch(searchValue: string): void {
this.searchValue = searchValue.toLowerCase();
}
}