-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathcourse_controller.js
102 lines (81 loc) · 2.92 KB
/
course_controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import { Controller } from '@hotwired/stimulus'
const LOADER_CLASSES = 'absolute bg-gray-100 opacity-10 w-full h-full'
export default class extends Controller {
static targets = ['countrySelectInput', 'citySelectInput', 'citySelectWrapper'];
static values = {
view: String,
}
// The fields initial value
static initialValue
get placeholder() {
return this.citySelectInputTarget.ariaPlaceholder
}
set loading(isLoading) {
if (isLoading) {
// create a loader overlay
const loadingDiv = document.createElement('div')
loadingDiv.className = LOADER_CLASSES
loadingDiv.dataset.target = 'city-loader'
// add the loader overlay
this.citySelectWrapperTarget.prepend(loadingDiv)
this.citySelectWrapperTarget.classList.add('opacity-50')
} else {
// remove the loader overlay
this.citySelectWrapperTarget.querySelector('[data-target="city-loader"]').remove()
this.citySelectWrapperTarget.classList.remove('opacity-50')
}
}
async connect() {
// Add the controller functionality only on forms
if (['edit', 'new'].includes(this.viewValue)) {
this.captureTheInitialValue()
// Trigger the change on load
await this.onCountryChange()
}
}
// Read the country select.
// If there's any value selected show the cities and prefill them.
async onCountryChange() {
if (this.hasCountrySelectInputTarget && this.countrySelectInputTarget) {
// Get the country
const country = this.countrySelectInputTarget.value
// Dynamically fetch the cities for this country
const cities = await this.fetchCitiesForCountry(country)
// Clear the select of options
Object.keys(this.citySelectInputTarget.options).forEach(() => {
this.citySelectInputTarget.options.remove(0)
})
// Add blank option
this.citySelectInputTarget.add(new Option(this.placeholder))
// Add the new cities
cities.forEach((city) => {
this.citySelectInputTarget.add(new Option(city, city))
})
// Check if the initial value is present in the cities array and select it.
// If not, select the first item
const currentOptions = Array.from(this.citySelectInputTarget.options).map((item) => item.value)
if (currentOptions.includes(this.initialValue)) {
this.citySelectInputTarget.value = this.initialValue
} else {
// Select the first item
this.citySelectInputTarget.value = this.citySelectInputTarget.options[0].value
}
}
}
// Private
captureTheInitialValue() {
this.initialValue = this.citySelectInputTarget.value
}
async fetchCitiesForCountry(country) {
if (!country) {
return []
}
this.loading = true
const response = await fetch(
`${window.Avo.configuration.root_path}/resources/courses/cities?country=${country}`,
)
const data = await response.json()
this.loading = false
return data
}
}