Browse Source

replaced select component with autocomplete

- add validation to allow only values from list
- add new interface type: platform
- autoselect value if input matches with an entry from list
pull/2429/head
Kevin Lien 2 years ago
committed by Thomas
parent
commit
00be7e1eea
  1. 67
      apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts
  2. 21
      apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html
  3. 2
      apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.module.ts
  4. 5
      apps/client/src/app/pages/accounts/create-or-update-account-dialog/interfaces/interfaces.ts

67
apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts

@ -4,14 +4,24 @@ import {
Inject, Inject,
OnDestroy OnDestroy
} from '@angular/core'; } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import {
AbstractControl,
FormBuilder,
FormGroup,
ValidatorFn,
Validators
} from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto'; import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto';
import { UpdateAccountDto } from '@ghostfolio/api/app/account/update-account.dto'; import { UpdateAccountDto } from '@ghostfolio/api/app/account/update-account.dto';
import { DataService } from '@ghostfolio/client/services/data.service'; import { DataService } from '@ghostfolio/client/services/data.service';
import { Subject } from 'rxjs'; import { Observable, Subject } from 'rxjs';
import { map, startWith } from 'rxjs/operators';
import { CreateOrUpdateAccountDialogParams } from './interfaces/interfaces'; import {
CreateOrUpdateAccountDialogParams,
Platform
} from './interfaces/interfaces';
@Component({ @Component({
host: { class: 'h-100' }, host: { class: 'h-100' },
@ -23,7 +33,8 @@ import { CreateOrUpdateAccountDialogParams } from './interfaces/interfaces';
export class CreateOrUpdateAccountDialog implements OnDestroy { export class CreateOrUpdateAccountDialog implements OnDestroy {
public accountForm: FormGroup; public accountForm: FormGroup;
public currencies: string[] = []; public currencies: string[] = [];
public platforms: { id: string; name: string }[]; public platforms: Platform[];
public filteredPlatforms: Observable<Platform[]>;
private unsubscribeSubject = new Subject<void>(); private unsubscribeSubject = new Subject<void>();
@ -47,8 +58,22 @@ export class CreateOrUpdateAccountDialog implements OnDestroy {
currency: [this.data.account.currency, Validators.required], currency: [this.data.account.currency, Validators.required],
isExcluded: [this.data.account.isExcluded], isExcluded: [this.data.account.isExcluded],
name: [this.data.account.name, Validators.required], name: [this.data.account.name, Validators.required],
platformId: [this.data.account.platformId] platformId: [
this.platforms.find(
(platform) => platform.id === this.data.account.platformId
),
this._autocompleteObjectValidator()
]
}); });
this.filteredPlatforms = this.accountForm
.get('platformId')
.valueChanges.pipe(
startWith(''),
map((value) => {
const name = typeof value === 'string' ? value : value?.name;
return name ? this._filter(name as string) : this.platforms.slice();
})
);
} }
public onCancel() { public onCancel() {
@ -63,9 +88,8 @@ export class CreateOrUpdateAccountDialog implements OnDestroy {
id: this.accountForm.controls['accountId'].value, id: this.accountForm.controls['accountId'].value,
isExcluded: this.accountForm.controls['isExcluded'].value, isExcluded: this.accountForm.controls['isExcluded'].value,
name: this.accountForm.controls['name'].value, name: this.accountForm.controls['name'].value,
platformId: this.accountForm.controls['platformId'].value platformId: this.accountForm.controls['platformId'].value.id
}; };
if (this.data.account.id) { if (this.data.account.id) {
(account as UpdateAccountDto).id = this.data.account.id; (account as UpdateAccountDto).id = this.data.account.id;
} else { } else {
@ -79,4 +103,33 @@ export class CreateOrUpdateAccountDialog implements OnDestroy {
this.unsubscribeSubject.next(); this.unsubscribeSubject.next();
this.unsubscribeSubject.complete(); this.unsubscribeSubject.complete();
} }
public autoCompleteCheck() {
const inputValue = this.accountForm.controls['platformId'].value;
const matchingEntry = this.platforms.find(
(platform) => platform.name === inputValue
);
this.accountForm.controls['platformId'].setValue(matchingEntry);
}
displayFn(platform: Platform) {
return platform && platform.name ? platform.name : '';
}
private _filter(value: string): Platform[] {
const filterValue = value.toLowerCase();
return this.platforms.filter((platformEntry) =>
platformEntry.name.toLowerCase().includes(filterValue)
);
}
private _autocompleteObjectValidator(): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } | null => {
if (typeof control.value === 'string') {
return { invalidAutocompleteObject: { value: control.value } };
}
return null;
};
}
} }

21
apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html

@ -42,12 +42,23 @@
<div [ngClass]="{ 'd-none': platforms?.length < 1 }"> <div [ngClass]="{ 'd-none': platforms?.length < 1 }">
<mat-form-field appearance="outline" class="w-100"> <mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Platform</mat-label> <mat-label i18n>Platform</mat-label>
<mat-select formControlName="platformId">
<mat-option [value]="null"></mat-option> <input
<mat-option *ngFor="let platform of platforms" [value]="platform.id" formControlName="platformId"
>{{ platform.name }}</mat-option matInput
placeholder="Platform"
type="text"
[matAutocomplete]="auto"
(blur)="autoCompleteCheck()"
/>
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
<mat-option
*ngFor="let platformEntry of filteredPlatforms | async"
[value]="platformEntry"
> >
</mat-select> {{platformEntry.name}}
</mat-option>
</mat-autocomplete>
</mat-form-field> </mat-form-field>
</div> </div>
<div> <div>

2
apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.module.ts

@ -7,6 +7,7 @@ import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select'; import { MatSelectModule } from '@angular/material/select';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { CreateOrUpdateAccountDialog } from './create-or-update-account-dialog.component'; import { CreateOrUpdateAccountDialog } from './create-or-update-account-dialog.component';
@ -21,6 +22,7 @@ import { CreateOrUpdateAccountDialog } from './create-or-update-account-dialog.c
MatFormFieldModule, MatFormFieldModule,
MatInputModule, MatInputModule,
MatSelectModule, MatSelectModule,
MatAutocompleteModule,
ReactiveFormsModule ReactiveFormsModule
] ]
}) })

5
apps/client/src/app/pages/accounts/create-or-update-account-dialog/interfaces/interfaces.ts

@ -3,3 +3,8 @@ import { Account } from '@prisma/client';
export interface CreateOrUpdateAccountDialogParams { export interface CreateOrUpdateAccountDialogParams {
account: Account; account: Account;
} }
export interface Platform {
id: string;
name: string;
}

Loading…
Cancel
Save