close
tony / Phone country display

Phone Country Select

This gist is a variant of Simple Select with some additional data and styling tweaks

Demo

Code

<div :scope="
        placeholder='Search...';
        searchInputId=new Date().getTime(); // This is clunky but necessary way to focus the input we need to give it an identifier - this will just generate a stable number id based on the current timestamp
        numberInputId=new Date().getTime() + 1;
        showOptions=false;
        allOptions=[['ie','Ireland'],['gb','England'],['fr','France']];
        selectedOption=allOptions.first;
        highlightedOption=[];
        prefixes={ie:'353',gb:'44',fr:'33'};
        filteredOptions=allOptions;"
     class="relative text-black border-2 border-gray-100" >
  <div class="flex">
    <button 
        type="button"
        class="gap-x-2 bg-white px-4 pr-2 py-2 hover:bg-gray-100 cursor-pointer flex justify-between items-center" 
        :click="scope.showOptions = !scope.showOptions; document.getElementById(scope.searchInputId).focus();" >
      <div class="flex items-center">
        <img :src="`/icons/flags/${scope.selectedOption[0].toLowerCase()}.svg`" class="w-5 h-5 mr-2" />
        <div :text="'+' + scope.prefixes[scope.selectedOption[0]]"></div>
      </div>
      <div class="transition duration-100 ease-out" :class="scope.showOptions ? 'rotate-180' : ''">
        <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
        </svg>
      </div>
    </button>
    <div class="flex-grow pl-1">
      <input name="phone_number" type="text" class="no-style h-full outline-none w-full" placeholder="1234567" :id="scope.numberInputId">
    </div>
    <input type="hidden" name="country_code" :value="scope.prefixes[scope.selectedOption[0]]" >
  </div>
  <div class="relative">
    <div class="transition ease-out duration-100 shadow opacity-0 absolute top-0 left-0 w-32 " :class="scope.showOptions ? 'transform opacity-100 scale-100' : 'transform opacity-0 scale-95 pointer-events-none' " >
      <div class="bg-white rounded p-2" style="max-height:300px;overflow-y:scroll">
        <input  type="text" 
                :id="scope.searchInputId" 
                :change="
                  scope.filteredOptions = scope.allOptions.search(this.value);
                  scope.highlightedOption = scope.filteredOptions.first;
                "
                :keypress.enter="
                  event.preventDefault();
                  if (scope.highlightedOption && scope.highlightedOption.length) {
                    scope.selectedOption = scope.highlightedOption
                  } else {
                    scope.highlightedOption = [];
                    scope.selectedOption = [];
                  }
                  scope.showOptions = false;
                  scope.filteredOptions = scope.allOptions;
                  document.getElementById(scope.numberInputId).focus();
                  this.value='';
                  "
                :keyup.up="
                  scope.highlightedOption = scope.filteredOptions.previousItem(scope.highlightedOption)"
                :keyup.down="
                  scope.highlightedOption = scope.filteredOptions.nextItem(scope.highlightedOption)"
                :placeholder="scope.placeholder" 
                class="mb-2 w-full outline-none" >
        <div :each="option, index in scope.filteredOptions" >
          <button :click="scope.selectedOption=option;
                          scope.highlightedOption = [];
                          document.getElementById(scope.numberInputId).focus();
                          scope.showOptions=false"
                  :class="scope.highlightedOption.sameAs(option) ? 'bg-gray-100 text-gray-700' : 'text-black'" 
                  class="flex w-full text-left rounded px-2 py-2 hover:bg-gray-100 cursor-pointer block items-center" 
                  type="button" 
                   >
            <img :src="`/icons/flags/${option[0].toLowerCase()}.svg`" class="w-5 h-5 mr-2" />
            <div :text="'+' + scope.prefixes[option[0]]"></div>
          </button>
        </div>
      </div>
    </div>  
  </div>
</div>