Geo Selector

Refines GEO options based on user selections

Code (86 LOC)

ERB (52 LOC)
app/views/geo_selectors/_demo.html.erb (52 LOC)
<form data-controller="geo-selector" class="m-4" style="max-width:600px">
<div class="form-group">
<%= select_tag :region,
options_for_select(regions.prepend("Select a region..."), @region),
placeholder: "Select a region...",
class: "form-control form-control-lg",
data: { reflex: "change->GeoSelectorReflex#select_region" } %>
</div>
<div data-target="geo-selector.subregionPlaceholder" class="form-group" hidden>
<div class="form-control form-control-lg">
<i class="fas fa-spinner fa-spin"></i>
Fetching subregions...
</div>
</div>
<% if @region %>
<div class="form-group">
<%= select_tag :subregion,
options_for_select(subregions(@region).prepend("Select a sub-region..."), @subregion),
placeholder: "Select a sub-region...",
class: "form-control form-control-lg",
data: { reflex: "change->GeoSelectorReflex#select_subregion" } %>
</div>
<div data-target="geo-selector.countryPlaceholder" class="form-group" hidden>
<div class="form-control form-control-lg">
<i class="fas fa-spinner fa-spin"></i>
Fetching countries...
</div>
</div>
<% if @subregion %>
<div class="form-group">
<%= select_tag :country,
options_for_select(countries(@region, @subregion).prepend("Select a country..."), @country),
placeholder: "Select a country...",
class: "form-control form-control-lg",
data: { reflex: "change->GeoSelectorReflex#select_country" } %>
</div>
<div data-target="geo-selector.detailPlaceholder" class="form-group" hidden>
<div class="form-control form-control-lg">
<i class="fas fa-spinner fa-spin"></i>
Fetching country details...
</div>
</div>
<% if @country %>
<h3>
<%= @country_instance&.emoji_flag %>
<%= @country %>
</h3>
<%= link_to "Learn about this country", "https://en.wikipedia.org/wiki/#{@country}", target: "_blank" %>
<% end %>
<% end %>
<% end %>
</form>
JavaScript (17 LOC)
app/javascript/controllers/geo_selector_controller.js (17 LOC)
import ApplicationController from './application_controller'
export default class extends ApplicationController {
static targets = [
'subregionPlaceholder',
'countryPlaceholder',
'detailPlaceholder'
]
beforeReflex (element, reflex) {
super.beforeReflex(element, reflex)
if (reflex === 'GeoSelectorReflex#select_region')
this.subregionPlaceholderTarget.hidden = false
if (reflex === 'GeoSelectorReflex#select_subregion')
this.countryPlaceholderTarget.hidden = false
if (reflex === 'GeoSelectorReflex#select_country')
this.detailPlaceholderTarget.hidden = false
}
}
Ruby (17 LOC)
app/reflexes/geo_selector_reflex.rb (17 LOC)
class GeoSelectorReflex < ApplicationReflex
def select_region
@region = session[:region] = element[:value].start_with?("Select a") ? nil : element[:value]
end
def select_subregion
@region = session[:region]
@subregion = session[:subregion] = element[:value].start_with?("Select a") ? nil : element[:value]
end
def select_country
@region = session[:region]
@subregion = session[:subregion]
@country = session[:country] = element[:value].start_with?("Select a") ? nil : element[:value]
@country_instance = ISO3166::Country.all.find { |country|
country.region == @region && country.subregion == @subregion && country.name == @country
}
end
end