Browse Source

feat: Add currency selector

pull/2487/head
Dhoni77 2 years ago
parent
commit
39a4a54bc3
  1. 28
      libs/ui/src/lib/currency-selector/currency-selector.component.html
  2. 8
      libs/ui/src/lib/currency-selector/currency-selector.component.scss
  3. 154
      libs/ui/src/lib/currency-selector/currency-selector.component.ts
  4. 24
      libs/ui/src/lib/currency-selector/currency-selector.module.ts

28
libs/ui/src/lib/currency-selector/currency-selector.component.html

@ -0,0 +1,28 @@
<input
autocapitalize="off"
autocomplete="off"
matInput
[formControl]="control"
[matAutocomplete]="currencyAutocomplete"
/>
<mat-autocomplete
#currencyAutocomplete="matAutocomplete"
[displayWith]="displayFn"
(optionSelected)="onUpdateCurrency($event)"
>
<ng-container *ngIf="!isLoading">
<mat-option
*ngFor="let currencyItem of filteredCurrencies"
class="line-height-1"
[value]="currencyItem.value"
>
{{ currencyItem.label }}
</mat-option>
</ng-container>
</mat-autocomplete>
<mat-spinner
*ngIf="isLoading"
class="position-absolute"
[diameter]="20"
></mat-spinner>

8
libs/ui/src/lib/currency-selector/currency-selector.component.scss

@ -0,0 +1,8 @@
:host {
display: block;
.mat-mdc-progress-spinner {
right: 0;
top: calc(50% - 10px);
}
}

154
libs/ui/src/lib/currency-selector/currency-selector.component.ts

@ -0,0 +1,154 @@
import { FocusMonitor } from '@angular/cdk/a11y';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
Input,
OnDestroy,
OnInit,
ViewChild
} from '@angular/core';
import { FormControl, NgControl } from '@angular/forms';
import {
MatAutocomplete,
MatAutocompleteSelectedEvent
} from '@angular/material/autocomplete';
import { MatFormFieldControl } from '@angular/material/form-field';
import { MatInput } from '@angular/material/input';
import { Subject, of, tap } from 'rxjs';
import {
debounceTime,
distinctUntilChanged,
switchMap,
takeUntil
} from 'rxjs/operators';
import { Currency } from '@ghostfolio/common/interfaces/currency.interface';
import { AbstractMatFormField } from '../symbol-autocomplete/abstract-mat-form-field';
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'[attr.aria-describedBy]': 'describedBy',
'[id]': 'id'
},
selector: 'gf-currency-autocomplete',
styleUrls: ['./currency-selector.component.scss'],
templateUrl: 'currency-selector.component.html',
providers: [
{
provide: MatFormFieldControl,
useExisting: CurrencySelectorComponent
}
]
})
export class CurrencySelectorComponent
extends AbstractMatFormField<Currency>
implements OnInit, OnDestroy
{
@Input() private currencies: Currency[] = [];
@Input() public isLoading = false;
@ViewChild(MatInput, { static: false }) private input: MatInput;
@ViewChild('currencyAutocomplete')
public currencyAutocomplete: MatAutocomplete;
public control = new FormControl();
public filteredCurrencies: Currency[] = [];
private unsubscribeSubject = new Subject<void>();
public constructor(
public readonly _elementRef: ElementRef,
public readonly _focusMonitor: FocusMonitor,
public readonly changeDetectorRef: ChangeDetectorRef,
public readonly ngControl: NgControl
) {
super(_elementRef, _focusMonitor, ngControl);
this.controlType = 'currency-autocomplete';
}
public ngOnInit() {
if (this.disabled) {
this.control.disable();
}
this.control.valueChanges
.pipe(
debounceTime(400),
distinctUntilChanged(),
takeUntil(this.unsubscribeSubject),
tap(() => {
this.isLoading = true;
this.changeDetectorRef.markForCheck();
}),
switchMap((query) => {
return of(
this.currencies.filter((currency) =>
currency.label.toLowerCase().includes(query?.toLowerCase() || '')
) || []
);
})
)
.subscribe((filteredCurrencies: Currency[]) => {
this.filteredCurrencies = filteredCurrencies;
this.isLoading = false;
this.changeDetectorRef.markForCheck();
});
}
public displayFn(currency: string) {
return currency;
}
public get empty() {
return this.input?.empty;
}
public focus() {
this.input.focus();
}
public ngDoCheck() {
if (this.ngControl) {
this.validateRequired();
this.errorState = this.ngControl.invalid && this.ngControl.touched;
this.stateChanges.next();
}
}
public onUpdateCurrency(event: MatAutocompleteSelectedEvent) {
super.value = {
value: event.option.value
} as Currency;
}
public set value(value: Currency) {
this.control.setValue(value);
super.value = value;
}
public ngOnDestroy() {
super.ngOnDestroy();
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
private validateRequired() {
const requiredCheck = super.required
? !super.value?.value &&
!this.currencies
.map((currency) => currency.value)
.includes(super.value.value)
: false;
if (requiredCheck) {
this.ngControl.control.setErrors({ invalidData: true });
}
}
}

24
libs/ui/src/lib/currency-selector/currency-selector.module.ts

@ -0,0 +1,24 @@
import { CommonModule } from '@angular/common';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { CurrencySelectorComponent } from './currency-selector.component';
@NgModule({
declarations: [CurrencySelectorComponent],
exports: [CurrencySelectorComponent],
imports: [
CommonModule,
FormsModule,
MatAutocompleteModule,
MatFormFieldModule,
MatInputModule,
MatProgressSpinnerModule,
ReactiveFormsModule
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class GfCurrencyAutocompleteModule {}
Loading…
Cancel
Save