I'm working with BootstrapVue
.
I have following problem. I have a b-form-input
where I'm searching for my number
over my b-form-select
. So I'm selecting 3 values and get a number in my input field and other way around - so it's an Autofill.
This works fine - and because of that I think I don't need to show you the code.
The problem is that I want to disable all selects (instead of the first) till the field before was selected.
I have problem that if I have multiple elements all will be updated. So if I input something in Input1
in the first element the second Input
of all other elements will be !disabled
Additional Info: IDParent
is a prop!
If you need any additional code, I can update my question!
<template>
<div>
<div class="mt-2" v-for="(IDChild, indexChild) in inputs" :key="indexChild">
<div>
<div class="mt-2">Number</div>
<b-form-input type="number" v-model="IDChild.Number" :value="IDChild.Number"></b-form-input>
</div>
<div>
<div class="mt-2">Input 1</div>
<b-form-select v-model="IDChild.Input1" :value="IDChild.Input1" :options="optionsInput1" @input="searchNumber(IDChild, IDParent, indexChild)"></b-form-select>
</div>
<div>
<div class="mt-2">Input 2</div>
<b-form-select :disabled="disabledInput2" v-model="IDChild.Input2" :value="IDChild.Input2" :options="optionsInput2" @input="searchNumber(IDChild, IDParent, indexChild)"></b-form-select>
</div>
<div>
<div class="mt-2">Input 3</div>
<b-form-select :disabled="disabledInput3" v-model="IDChild.Input3" :value="IDChild.Input3" :options="optionsInput3" @input="searchNumber(IDChild, IDParent, indexChild)"></b-form-select>
</div>
</div>
<!-- add new element when button was clicked -->
<div class="mt-4 mb-5 ml-3 mr-3">
<b-button @click="addElement"> Add Element </b-button>
</div>
</div>
</template>
my script:
<script>
import json from "./json/json.json";
export default {
name: "Test",
methods: {
addElement() {
this.inputs.push({});
},
searchNumber(input, IDParent, indexChild) {
input.Number = "";
this.json.forEach((element) => {
if (
element.Input1 == input.Input1 &&
element.Input2 == input.Input2 &&
element.Input3 == input.Input3
) {
for (const key of Object.keys(element)) {
input[key] = element[key];
}
}
});
if(input.Input1) {
this.disabledInput2 = false;
}
if(input.Input2) {
this.disabledInput3 = false;
}
},
},
props: [
"IDParent",
],
data() {
return {
inputs: [{}],
json: json,
disabledInput2: true,
disabledInput3: true,
};
},
};
</script>
CodePudding user response:
What you are missing is a multi-layer model for your data which you can call in your searchNumber
function and call for your :disabled
attribute.
In your v-for="(IDChild, indexChild) in inputs"
you could use IDChild
or indexChild
for that. For example you would call :disabled="disabledInput2[indexChild]"
. That way you would refer to disabledInput2
with the specific indexChild
.
You also need to handle this in your function, for example this.disabledInput2[indexChild] = false;
.
Basically it´s the same as storing multi-layer data in the same object with v-model
. Let me know, if this helped you.
EDIT: Generally Example
I´ve created the following properties for this example. We have myNumberInput
as an object to handle multiple input fields for numbers. mySelectionData
provides a simple collection of two objects with 3 selection arrays each. myDisableData
is the object that will handle multiple disabled
attributes for this selections:
myNumberInput: {},
mySelectionData: {
1: {
1: [
{ name: "1A", value: 1 }, { name: "2A", value: 2 }, { name: "3A", value: 3 }
],
2: [
{ name: "4A", value: 4 }, { name: "5A", value: 5 }, { name: "6A", value: 6 }
],
3: [
{ name: "7A", value: 7 }, { name: "8A", value: 8 }, { name: "9A", value: 9 }
]
},
2: {
1: [
{ name: "1B", value: 11 }, { name: "2B", value: 21 }, { name: "3B", value: 31 }
],
2: [
{ name: "4B", value: 41 }, { name: "5B", value: 51 }, { name: "6B", value: 61 }
],
3: [
{ name: "7B", value: 71 }, { name: "8B", value: 81 }, { name: "9B", value: 91 }
]
}
},
myDisableData: {}
From the mySelectionData
object, we will build our myDisableData
with this function:
setupMyDisableData() {
Object.keys(this.mySelectionData).forEach(parent_key => {
Object.assign(this.myDisableData, {[parent_key]: {}})
Object.keys(this.mySelectionData[parent_key]).forEach(child_key => {
Object.assign(this.myDisableData[parent_key], {[child_key]: true})
});
});
}
This will loop trough our "parents", assign their index
to myDisableData
and also loop trough the "childs" and assign their index
to myDisableData
with the "parent"-index
as a pointer. After that we have a multi-layer object which is able to provide diabled=
true
or false
for each selection.
The html for this example looks like this:
<div v-for="(item,index) in mySelectionData" :key="index">
<input type="number" v-model="myNumberInput[index]" @input="enableMySelection(index, myNumberInput[index])">
<div v-for="(child_item, child_index) in item" :key="child_index">
<select :disabled="myDisableData[index][child_index]">
<option v-for="(child_option, child_option_index) in child_item" :key="child_option_index" :value="child_option.value">{{child_option.name}}</option>
</select>
</div>
</div>
As I don´t use BootstrapVue
, my html looks different, but I guess you will get the trick. You simply now refer to the three object by the index
of "parent" and "child". In this example the function enableMySelection
will enable a selection depending on the number entered in the input
. The function looks like this:
enableMySelection(parent_index, input_number) {
Object.keys(this.myDisableData[parent_index]).forEach(child_key => {
this.myDisableData[parent_index][child_key] = true;
});
this.myDisableData[parent_index][input_number] = false;
}
So if you enter "2" in your first input, it will enable the second selection of the first block. If you enter 1 in the second input, it will enable the first selection in the second block.
As I said, this is just a generally example but this should be enough to help you define the structure to handle your multiple inputs and selections.