Thank you for answering but I don't know how to make it work. I'll share the code with you:
HTML:
<div class="input-field col-md-5">
<label for="phonePrefix">{{
"reservation.labels.prefix" | translate
}}</label>
<div class="prefix d-flex">
<div class="flag-img">
<img [src]="selectedCountryImage" alt="" class="prefix-flag" />
</div>
<input
type="tel"
name="phonePrefix"
id="phonePrefix"
formControlName="phonePrefix"
(input)="onInput($event)"
(keydown)="validateNumber($event)"
(focus)="onFocus()"
(blur)="onBlur()"
pattern="[+0-9]*"
autocomplete="new-password"
inputmode="numeric"
/>
</div>
<div class="countries-prefix" *ngIf="showDropdown">
<div class="scrollable-content">
<ul>
<li
*ngFor="let country of filteredCountries"
(click)="onPrefixSelect(country.dialCodes)"
[class]="{ 'highlight': i === 0}"
>
<img
[src]="country.image"
alt="Flag"
class="country-flag"
/>
<span class="country-option">
{{ country.dialCodes }} {{ country.name }}
</span>
</li>
</ul>
</div>
</div>
<p class="suggestion">
{{ "reservation.suggestions.prefix" | translate }}
</p>
</div>
And this is the .ts:
import { Component, OnInit } from '@angular/core';
import {
FormsModule,
FormControl,
FormGroup,
ReactiveFormsModule,
} from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { TranslateService } from '@ngx-translate/core';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { faUser, faEnvelope, faUsers, faMobile, faMapPin, faEuroSign } from '@fortawesome/free-solid-svg-icons';
import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-reservation',
standalone: true,
imports: [
ReactiveFormsModule,
FaIconComponent,
CommonModule,
NgbDatepickerModule,
FormsModule,
TranslateModule,
],
templateUrl: './reservation.component.html',
styleUrls: ['./reservation.component.css'],
})
export class ReservationComponent implements OnInit {
// REACTIVE FORM
profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
email: new FormControl(''),
numberOfPeople: new FormControl(''),
phonePrefix: new FormControl(''),
phoneNumber: new FormControl(''),
});
// FA-ICONS
faUser = faUser;
faEnvelope = faEnvelope;
faUsers = faUsers;
faMobile = faMobile;
faMapPin = faMapPin;
faEuroSign = faEuroSign;
// DATEPICKER
displayMonths = 2;
navigation = 'select';
showWeekNumbers = false;
outsideDays = 'visible';
// MANAGE COUNTRIES
countries: any[] = [];
filteredCountries: any[] = [];
selectedCountryImage: string | null = null;
highlightedCountry: any;
showDropdown: boolean = false;
i: any;
constructor(private http: HttpClient, private translate: TranslateService) {}
ngOnInit(): void {
// Get countries
this.http
.get<any[]>('./../../../assets/data/countries.json')
.subscribe((data) => {
this.countries = data;
this.filteredCountries = [...this.countries]; // Initialize with all countries
});
// Optional: Subscribe to value changes for more dynamic filtering
this.profileForm.get('phonePrefix')?.valueChanges.subscribe((value) => {
this.filterCountries(value);
});
}
// DROPDOWN
onFocus(): void {
this.showDropdown = true; // Show all countries on focus
}
onBlur(): void {
// Hide dropdown after a short delay to allow clicks
setTimeout(() => {
this.showDropdown = false;
}, 100);
}
// FILTER COUNTRIES
filterCountries(input: string | null): void {
if (input) {
const normalizedInput = input.replace(/\D/g, '');
this.filteredCountries = this.countries.filter((country) =>
country.dialCodes.some((dialCode: string) => dialCode.replace(/\D/g, '').includes(normalizedInput))
);
if(this.filterCountries.length > 0) {
this.highlightedCountry = this.filteredCountries[0];
}
const selectedCountry = this.filteredCountries.find(
country => country.dialCodes.some((dialCode: string)=> dialCode.replace(/\D/g, '') === normalizedInput)
);
this.selectedCountryImage = selectedCountry ? selectedCountry.image : null; // Set image if found
} else {
this.filteredCountries = [...this.countries];
this.highlightedCountry = null;
}
}
// Find country and update flag
onPrefixSelect(dialCode: string): void {
this.profileForm.get('phonePrefix')?.setValue(dialCode);
const selectedCountry = this.countries.find(
(country) => country.dialCodes === dialCode // Use comparison, not assignment
);
this.selectedCountryImage = selectedCountry ? selectedCountry.image : null; // Set image if found
this.showDropdown = false; // Hide dropdown after selection
}
onPrefixClear(): void {
this.selectedCountryImage = null;
}
validateNumber(event: KeyboardEvent): void {
const allowedKeys = ['Backspace', 'ArrowLeft', 'ArrowRight', 'Tab'];
const isNumberKey = /^[0-9]$/.test(event.key);
const isPlusKey = event.key === '+';
if (!isNumberKey && !isPlusKey && !allowedKeys.includes(event.key)) {
event.preventDefault();
}
}
onInput(event: Event): void {
const inputValue = (event.target as HTMLInputElement)?.value || "";
this.filterCountries(inputValue);
}
}
PS: I apologize if some of this doesn't make sense, I'm a beginner :)