79118075

Date: 2024-10-23 13:22:00
Score: 2.5
Natty:
Report link

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 :)

Reasons:
  • Blacklisted phrase (0.5): Thank you
  • RegEx Blacklisted phrase (2): I'm a beginner
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • Low reputation (1):
Posted by: sg9