Topic: Multiple mdbSelect With Identical Options
atticuss free asked 3 years ago
I'm building a recipe application to learn a few different technologies. When creating a new recipe, the user can add an arbitrary number of ingredients. I solved this with the following snippet of relevant template code:
<mdb-tbl>
<mdb-row
v-for="idx in numIngredients"
:index="idx"
:key="idx"
class="justify-content-start"
>
<mdb-col col="7">
<mdb-select
v-model:"ingredients"
placeholder="Select an ingredient"
label=""
search
>
</mdb-select>
</mdb-col>
</mdb-row>
</mdb-tbl>
And within the script code, I load all the ingredients via axios:
created() {
IngredientAPI.getIngredients().then(data => {
this.ingredients = data.ingredients.map(ing => {
return { text: ing.name, value: ing.uid };
});
});
}
This works great for a single mdbSelect, but I (obviously) need to add multiple ingredients. By using v-model
, the two binding makes it so that any update to one mdbSelect updates all mdbSelect components. Expected behavior. However, I'm struggling with how to fix this behavior. I've tried a several solutions to no avail. For example:
<mdb-select
:options="ingredients"
:selected="getSelected(idx)"
@change="updateSelected($event, idx)"
placeholder="Select an ingredient"
label=""
search
/>
getSelected(idx) {
console.log(`get selected: ${idx}`);
return this.selectedIngredients[idx];
},
updateSelected(val, idx) {
console.log(`update selected: ${val} - ${idx}`);
this.selectedIngredients[idx] = { text: val, value: val };
},
Or:
<mdb-select
v-model="ingredients"
:selected="selectedIngredients[idx]"
placeholder="Select an ingredient"
label=""
search
/>
The obvious solution is to create a separate array for each mdbSelect; however, this feels incredibly hacky and would almost certainly cause performance issues once I have hundreds of ingredient choices. Is there a way to provide each mdbSelect with a list of options whilst maintaining a list of what each mdbSelect has selected independently? Thanks in advance.
FREE CONSULTATION
Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.
Resolved
- ForumUser: Free
- Premium support: No
- Technology: MDB Vue
- MDB Version: 6.7.2
- Device: PC
- Browser: Firefox
- OS: OSX
- Provided sample code: Yes
- Provided link: No
Mikołaj Smoleński staff commented 3 years ago
In such case it's necessary to create a new list for each select. Best regards
atticuss free commented 3 years ago
Well that's pretty unfortunate. But I anticipated this and decided to not preload any items and instead rely on the
@search
and adisableFilter
. However, I'm having trouble getting my array to be reactive to data changes. For example:this.ingredients[0]
updates just fine, but the items are not added to the list presented by mdbSelect. I'm guessing this has to do with an implementation detail of howv-model
handles two-way binding? It's worth noting this works fine if I just bind toingredients
, and that I'm only explicitly indexing at 0 as a POC.atticuss free commented 3 years ago
Ah sorry -- still new to Vue and just found the reactivity caveats within the docs. If anyone stumbles across this later, the solution is to replace:
with:
This will trigger state updates and update component data accordingly. More info for noobs like me:
https://vuejs.org/v2/guide/reactivity.html#For-Arrays
That said: I'd heavily recommend you consider expanding the mdbSelect component to be able to easily delineate between a list of options and the selected value. I can't imagine this use-case is very novel, and it hurts my inner engineer to see data pointlessly copied like in the originally proposed solution.