Browse Source

UI: Fixed country autocomplete after review

pull/14802/head
Vladyslav_Prykhodko 9 months ago
parent
commit
6f03b8ae2f
  1. 6
      ui-ngx/src/app/core/utils.ts
  2. 4
      ui-ngx/src/app/shared/components/country-autocomplete.component.html
  3. 10
      ui-ngx/src/app/shared/components/country-autocomplete.component.scss
  4. 49
      ui-ngx/src/app/shared/components/country-autocomplete.component.ts
  5. 2
      ui-ngx/src/assets/locale/locale.constant-en_US.json

6
ui-ngx/src/app/core/utils.ts

@ -999,11 +999,11 @@ export const validateEmail = (control: AbstractControl): ValidationErrors | null
return emailRegex.test(control.value) ? null : {email: true}; return emailRegex.test(control.value) ? null : {email: true};
}; };
export const requireMatch = (): ValidatorFn => { export const objectRequired = (): ValidatorFn => {
return (control: AbstractControl): ValidationErrors | null => { return (control: AbstractControl): ValidationErrors | null => {
const value = control.value; const value = control.value;
if (value && typeof value === 'string') { if (value && !isObject(value)) {
return { requireMatch: { value: value } }; return { objectRequired: true };
} }
return null; return null;
}; };

4
ui-ngx/src/app/shared/components/country-autocomplete.component.html

@ -61,7 +61,7 @@
<mat-error *ngIf="countryFormGroup.get('country').hasError('required')"> <mat-error *ngIf="countryFormGroup.get('country').hasError('required')">
{{ requiredText }} {{ requiredText }}
</mat-error> </mat-error>
<mat-error *ngIf="countryFormGroup.get('country').hasError('requireMatch')"> <mat-error *ngIf="countryFormGroup.get('country').hasError('objectRequired')">
{{ requiredMatchText }} {{ objectRequiredText }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>

10
ui-ngx/src/app/shared/components/country-autocomplete.component.scss

@ -17,11 +17,13 @@
.mat-form-field-appearance-fill { .mat-form-field-appearance-fill {
.mat-mdc-form-field-icon-prefix { .mat-mdc-form-field-icon-prefix {
align-self: baseline; align-self: baseline;
}
}
& > * { .mat-mdc-form-field-icon-prefix {
color: initial; & > * {
padding-left: 8px; color: initial;
} padding-left: 8px;
} }
} }
} }

49
ui-ngx/src/app/shared/components/country-autocomplete.component.ts

@ -14,7 +14,18 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, ElementRef, EventEmitter, forwardRef, Input, OnInit, Output, ViewChild } from '@angular/core'; import {
Component,
ElementRef,
EventEmitter,
forwardRef,
Input,
OnChanges,
OnInit,
Output,
SimpleChanges,
ViewChild
} from '@angular/core';
import { Country, CountryData } from '@shared/models/country.models'; import { Country, CountryData } from '@shared/models/country.models';
import { import {
ControlValueAccessor, ControlValueAccessor,
@ -26,7 +37,7 @@ import {
Validator, Validator,
Validators Validators
} from '@angular/forms'; } from '@angular/forms';
import { isNotEmptyStr, requireMatch } from '@core/utils'; import { isNotEmptyStr, objectRequired } from '@core/utils';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators'; import { debounceTime, distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators';
import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field'; import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field';
@ -56,7 +67,7 @@ interface CountrySearchData extends Country {
} }
] ]
}) })
export class CountryAutocompleteComponent implements OnInit, ControlValueAccessor, Validator { export class CountryAutocompleteComponent implements OnInit, OnChanges, ControlValueAccessor, Validator {
@Input() @Input()
labelText = this.translate.instant('contact.country'); labelText = this.translate.instant('contact.country');
@ -65,7 +76,7 @@ export class CountryAutocompleteComponent implements OnInit, ControlValueAccesso
requiredText = this.translate.instant('contact.country-required'); requiredText = this.translate.instant('contact.country-required');
@Input() @Input()
requiredMatchText = this.translate.instant('contact.country-required-match'); objectRequiredText = this.translate.instant('contact.country-object-required');
@Input() @Input()
autocompleteHint: string; autocompleteHint: string;
@ -111,15 +122,25 @@ export class CountryAutocompleteComponent implements OnInit, ControlValueAccesso
private countryData: CountryData, private countryData: CountryData,
private translate: TranslateService) { private translate: TranslateService) {
this.countryFormGroup = this.fb.group({ this.countryFormGroup = this.fb.group({
country: ['', requireMatch()] country: ['', objectRequired()]
}); });
} }
ngOnInit(): void { ngOnChanges(changes: SimpleChanges) {
if (this.required) { if (changes.required) {
this.countryFormGroup.get('country').addValidators(Validators.required); const requiredChanges = changes.required;
this.countryFormGroup.get('country').updateValueAndValidity(); if (requiredChanges.currentValue !== requiredChanges.previousValue) {
if (requiredChanges.currentValue) {
this.countryFormGroup.get('country').addValidators(Validators.required);
} else {
this.countryFormGroup.get('country').removeValidators(Validators.required);
}
this.countryFormGroup.get('country').updateValueAndValidity();
}
} }
}
ngOnInit(): void {
this.filteredCountries = this.countryFormGroup.get('country').valueChanges.pipe( this.filteredCountries = this.countryFormGroup.get('country').valueChanges.pipe(
debounceTime(150), debounceTime(150),
tap(value => { tap(value => {
@ -190,12 +211,10 @@ export class CountryAutocompleteComponent implements OnInit, ControlValueAccesso
const value = control.value; const value = control.value;
if (value && typeof value === 'string') { if (value && typeof value === 'string') {
const filterValue = value.trim().toLowerCase(); const foundCountry = this.fetchCountries(value);
const foundCountry = this.allCountries.find(c => c.name.toLowerCase() === filterValue); if (foundCountry.length === 1) {
control.setValue(foundCountry[0]);
if (foundCountry) { this.autocompleteTrigger?.closePanel();
control.setValue(foundCountry);
this.autocompleteTrigger.closePanel();
} }
} }

2
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -1194,7 +1194,7 @@
"contact": { "contact": {
"country": "Country", "country": "Country",
"country-required": "Country is required.", "country-required": "Country is required.",
"country-required-match": "Please select a valid country from the list.", "country-object-required": "Please select a valid country from the list.",
"city": "City", "city": "City",
"state": "State / Province", "state": "State / Province",
"postal-code": "Zip / Postal Code", "postal-code": "Zip / Postal Code",

Loading…
Cancel
Save