Initially, in my Vue component, I had a series of nested if statements to iterate through the JSON data and determine whether to display a text input or a select based on a has_selectable_value
option being true (displaying select) or false (displaying text input). However, I have now transitioned to using a computed statement that accomplishes most of what I need, except for displaying the select options.
Below is the relevant part of the Vue Code:
<template v-else-if="searchtype == 9">
<select v-for="service in selectableServices" class="form-control" v-model="searchvalue" required>
<option value="">Select A Location</option>
<option v-for="sl in selectableLocations" :value="sl.location_id">{{sl.name}}</option>
</select>
<input v-for="service in nonSelectableServices" class="form-control" v-model="searchvalue" placeholder="Enter Search Value" required>
</template>
The existing computed functions are as follows:
services: function () {
var ret = []
this.countries.forEach(function(country) {
country.states.forEach(function(state) {
state.services.forEach(function(service) {
ret.push(service)
});
});
});
return ret;
},
selectableServices: function () {
return this.services.filter(service => service.id == this.service && service.has_selectable_location);
},
nonSelectableServices: function () {
return this.services.filter(service => service.id == this.service && !service.has_selectable_location);
},
selectableLocations: function () {
// Filtering one more level down
return this.selectableServices.map(service => service.selectablelocations);
},
This is the structure of the JSON data being worked with (relevant parts only):
[
{
"id": 1,
"name": "Country Name",
"states": [
{
"id": 1,
"name": "State Name",
"services": [
{
"id": 1,
"name": "Service Name",
"has_selectable_location": 1,
"selectablelocations": [
{
"id": 1,
"name": "Selectable Location A",
},
]
}
]
}
]
}
]
By using a Vue plugin for Chrome, it was observed that the computed function selectableLocations
loads an array containing the individual locations, but the current v-for statement is unable to function correctly. Therefore, another level needs to be added by incorporating an extra v-for loop like so:
<template v-for="selectableLocationsList in selectableLocations" >
<option v-for="sl in selectableLocationsList" :value="sl.location_id">{{sl.name}}</option>
</template>
While everything displays correctly with this approach, there might be better practices available. The aim was to handle most of this within computed functions and ideally utilize just a single v-for statement. If this limitation remains, I am willing to maintain the existing setup.
Thank you for your help.
Edit: Following additional testing and research, the following code was devised to achieve the desired outcome:
var formArray = []
var locationsArray = this.servicesArray.filter(service => service.id == this.service);
locationsArray.map(service => service.selectablelocations);
locationsArray.forEach(function(selectableLocations) {
selectableLocations.selectablelocations.forEach(function(location) {
formArray.push(location)
});
});
return formArray;
Is there a way to further optimize this code for cleaner execution?