I'm working on a simple form that shows 3 elements
A user enters 2 barcodes in each field. The first 2 digits of the barcodeEnd value gets compared against the allBarcodePrefixes data to see if there is a match, and prints the corresponding agency name or "Agency Not Found" if there is no match. If there is no match, the form stops there (user must fix the barcode entry) but if it finds a match it brings up a new line with a newly generated set of field and v-models
This was working fine until I made the v-models dynamic so I can manipulate each entry independently for validations and value
PROBLEM Two odd things are happening I need help with guys.
showAgencyName()
method is supposed to get the v-model and compare it to the data to get the agency name. But my v-model is dynamic and in a string literal. I'm not sure how to pull this valueI have the code in a codepen for you to check it out and see what I mean. I put the onAddBarcodes
function in the failing line so you can see it validate correctly (that part works). Eventually, this line will be removed since it's only supposed to validate for minLength and maxLength after it validated for the agency first.
<div id="q-app">
<div class="q-pa-md">
<div>
<div v-for="(barcode, index) in barcodes" :key="index">
<div class="full-width row no-wrap justify-start items-center q-pt-lg">
<div class="col-3">
<label>Starting Roll #:</label>
<q-input outlined square dense v-model="$v[`barcodeStart${index}`].$model"></q-input>
<div class="error-msg">
<div v-if="!$v[`barcodeStart${index}`].maxLength || !$v[`barcodeStart${index}`].minLength">
<span> Must be exactly 9 characters. </span>
</div>
</div>
</div>
<div class="col-3">
<label>Ending Roll #:</label>
<q-input outlined square dense v-model="$v[`barcodeEnd${index}`].$model" @change="showAgencyName(barcode)"></q-input>
<div class="error-msg">
<div v-if="!$v[`barcodeEnd${index}`].maxLength || !$v[`barcodeEnd${index}`].minLength">
<span> Must be exactly 9 characters. </span>
</div>
</div>
</div>
<div class="col-3">
<label>Agency:</label>
<div v-if="barcode.agencyName">
{{ barcode.agencyName }}
</div>
<div v-else></div>
</div>
</div>
</div>
</div>
</div>
</div>
Vue.use(window.vuelidate.default)
const { required, minLength, maxLength } = window.validators
new Vue({
el: '#q-app',
data () {
return {
barcodes: [
{
barcodeStart: "",
barcodeEnd: "",
agencyName: ""
}
],
newPackage: "",
reset: true,
allBarcodePrefixes: {
"10": "Boston",
"11": "New York",
"13": "Houston",
"14": "Connecticut",
"16": "SIA",
"17": "Colorado",
"18": "Chicago"
}
}
},
validations() {
const rules = {};
this.barcodes.forEach((barcode, index) => {
rules[`barcodeStart${index}`] = {
minLength: minLength(9),
maxLength: maxLength(9)
};
});
this.barcodes.forEach((barcode, index) => {
rules[`barcodeEnd${index}`] = {
minLength: minLength(9),
maxLength: maxLength(9)
};
});
return rules;
},
methods: {
onAddBarcodes() {
// creating a new line when requested on blur of barcodeEnd
const newBarcode = {
barcodeStart: "",
barcodeEnd: "",
agencyName: ""
};
this.barcodes.push(newBarcode);
},
showAgencyName(barcode) {
var str = barcode.barcodeEnd; // I need to pull the v-model value
var res = str.substring(0, 2); //get first 2 char of v-model
if (this.allBarcodePrefixes[res] == undefined) {
//compare it to data
barcode.agencyName = "Agency not found"; //pass this msg if not matched
this.onAddBarcodes(); //adding it to the fail just for testing
} else {
barcode.agencyName = this.allBarcodePrefixes[res]; //pass this if matched
this.onAddBarcodes(); //bring up a new line
}
},
}
})
Thanks in advance!
What you can do is set the v-model to the object in your v-for loop. So that it will look like this.
<q-input outlined square dense v-model="barcode.barcodeStart"></q-input>
and
<q-input outlined square dense v-model="barcode.barcodeEnd"></q-input>
This way they update the barcode object and due to it being an observable your showAgencyName
function can stay as it is and the barcode object in it will be updated.
EDIT
When you call the onchange event you can then pass through the index
@change="showAgencyName(barcode, index)"
then in your showAgencyName function you can access the validation with this.$v
.
To make sure the rules have past you will need to update the $model
. Like this
this.$v[`barcodeStart${index}`].$model = barcode.barcodeStart
this.$v[`barcodeEnd${index}`].$model = barcode.barcodeEnd
// Check for errors
if (this.$v[`barcodeEnd${index}`].$error) {
return
}