Browse Source

Reuse currency selector

pull/7584/head
Thomas Kaul 3 weeks ago
parent
commit
b1d85c5735
  1. 11
      apps/client/src/app/components/user-account-settings/user-account-settings.component.ts
  2. 2
      apps/client/src/app/components/user-account-settings/user-account-settings.html
  3. 29
      libs/ui/src/lib/currency-selector/currency-selector.component.ts
  4. 20
      libs/ui/src/lib/shared/abstract-mat-form-field.ts

11
apps/client/src/app/components/user-account-settings/user-account-settings.component.ts

@ -32,7 +32,6 @@ import {
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import {
NonNullableFormBuilder,
FormBuilder,
FormsModule,
ReactiveFormsModule,
Validators
@ -80,9 +79,8 @@ import { catchError } from 'rxjs/operators';
})
export class GfUserAccountSettingsComponent implements OnInit {
protected readonly appearancePlaceholder = $localize`Auto`;
protected readonly baseCurrency: string;
protected readonly baseCurrencyForm = inject(FormBuilder).group({
baseCurrency: ['']
protected readonly baseCurrencyForm = inject(NonNullableFormBuilder).group({
baseCurrency: [{ value: '', disabled: true }]
});
protected closeUserAccountMailHref: string;
protected readonly currencies: string[] = [];
@ -135,9 +133,8 @@ export class GfUserAccountSettingsComponent implements OnInit {
private readonly webAuthnService = inject(WebAuthnService);
public constructor() {
const { baseCurrency, currencies } = this.dataService.fetchInfo();
const { currencies } = this.dataService.fetchInfo();
this.baseCurrency = baseCurrency;
this.currencies = currencies;
this.userService.stateChanged
@ -189,7 +186,7 @@ export class GfUserAccountSettingsComponent implements OnInit {
);
this.baseCurrencyForm.setValue(
{ baseCurrency: this.user.settings.baseCurrency ?? null },
{ baseCurrency: this.user.settings.baseCurrency ?? '' },
{ emitEvent: false }
);

2
apps/client/src/app/components/user-account-settings/user-account-settings.html

@ -3,7 +3,7 @@
<div class="row">
<div class="col">
<div class="d-flex py-1">
<form #changeUserSettingsForm="ngForm" class="w-100">
<form class="w-100">
<div class="d-flex mb-2">
<div class="align-items-center d-flex pt-1 pt-1 w-50">
<ng-container i18n>Base Currency</ng-container>

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

@ -30,6 +30,7 @@ import {
MatAutocomplete,
MatAutocompleteModule,
MatAutocompleteOrigin,
MatAutocompleteTrigger,
MatOption
} from '@angular/material/autocomplete';
import {
@ -78,9 +79,13 @@ export class GfCurrencySelectorComponent
public filteredCurrencies: string[] = [];
public readonly formControlName = input.required<string>();
private readonly autocompleteTrigger = viewChild.required(
MatAutocompleteTrigger
);
private readonly destroyRef = inject(DestroyRef);
private readonly formField = inject(MAT_FORM_FIELD);
private readonly input = viewChild.required(MatInput);
private lastSelectedCurrency: string | null = null;
public constructor(
public override readonly _elementRef: ElementRef,
@ -113,6 +118,8 @@ export class GfCurrencySelectorComponent
public override set value(value: string | null) {
this.control.setValue(value);
super.value = value;
this.lastSelectedCurrency = value;
}
public focus() {
@ -170,16 +177,24 @@ export class GfCurrencySelectorComponent
}
}
public override onBlur() {
// Typing clears the selected currency, so restore the last selection once
// the user leaves the field without picking an option. The panel is still
// open while an option is being clicked, in which case the selection
// itself provides the new value.
if (!super.value && !this.autocompleteTrigger().panelOpen) {
this.value = this.lastSelectedCurrency;
this.changeDetectorRef.markForCheck();
}
super.onBlur();
}
public onUpdateCurrency({ option }: { option: MatOption<string> }) {
super.value = option.value;
}
public setDisabledState(isDisabled: boolean) {
if (isDisabled) {
this.control.disable({ emitEvent: false });
} else {
this.control.enable({ emitEvent: false });
}
this.lastSelectedCurrency = option.value;
}
private filter(value: string) {

20
libs/ui/src/lib/shared/abstract-mat-form-field.ts

@ -9,7 +9,12 @@ import {
Input,
OnDestroy
} from '@angular/core';
import { ControlValueAccessor, NgControl, Validators } from '@angular/forms';
import {
ControlValueAccessor,
FormControl,
NgControl,
Validators
} from '@angular/forms';
import { MatFormFieldControl } from '@angular/material/form-field';
import { Subject } from 'rxjs';
@ -23,6 +28,7 @@ export abstract class AbstractMatFormField<T>
@HostBinding('attr.aria-describedBy') public describedBy = '';
public readonly autofilled: boolean;
public abstract readonly control: FormControl;
public errorState: boolean;
public focused = false;
public readonly stateChanges = new Subject<void>();
@ -156,6 +162,18 @@ export abstract class AbstractMatFormField<T>
this.describedBy = ids.join(' ');
}
public setDisabledState(isDisabled: boolean) {
if (isDisabled) {
this.control.disable({ emitEvent: false });
} else {
this.control.enable({ emitEvent: false });
}
this.disabled = isDisabled;
this.stateChanges.next();
}
public writeValue(value: T) {
this.value = value;
}

Loading…
Cancel
Save