Reputation: 10240
I have a form that adds a new line on a button click. The new line must check for logic independently. In this case, it's chacking the first 2 digits of a barcode and associating it to a data set to see if it matches and return the appropriate value or "nothing found". I can't seem to get this right. First, it's not really evaluating at all. It only gives me "No Agency found" and second, it's doing it for all fields (because they all have the same v-model on a new line add). How can I achieve this so that it evaluates correctly and independently from each other?
Here's the relevant code in my template and script
<div id="q-app" class="q-pa-lg">
<div class="col-6">
<div v-for="(barcodefield, index) in barcodefields" :key="index">
<div class="flex q-pt-lg">
<div class="row flex-center">
<div class="col-3">
<div class="column">
<div class="row q-pr-lg items-center">
<label class="text-weight-medium">Starting Roll #:</label>
<q-input outlined square dense maxlength="24"
v-model.trim="barcodefield.start" ref="bcentry"></q-input>
</div>
</div>
</div>
<div class="col-3">
<div class="column">
<div class="row q-pr-lg items-center">
<label class="text-weight-medium">Ending Roll #:</label>
<q-input outlined square dense maxlength="24"
v-model.trim="barcodefield.end" @blur="showAgencyName" ref="bcentry"></q-input>
</div>
</div>
</div>
<div class="col-5">
<div class="column">
<label class="text-weight-medium">
Agency:
</label>
<div v-if="agencyName" style="min-height: 40px">
{{ agencyName }}
</div>
<div v-else style="min-height: 40px"></div>
</div>
</div>
<div class="col-1">
<div class="block float-right">
<q-btn v-if="index + 1 === barcodefields.length" @click="addLine" icon="add" color="primary" round />
<q-btn v-else style="min-width: 42px"/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
export default {
data() {
return {
barcodefields: [],
barcodeprefixes: {
"10": "Boston",
"11": "New York",
"13": "Houston",
"14": "Connecticut",
"16": "SIA",
"17": "Colorado",
"18": "Chicago",
"19": "Washington",
},
barcodefield: {
star: "",
end: ""
},
agencyName: "",
};
},
methods: {
addLine() {
this.barcodefields.push({
start: null,
end: null
});
},
showAgencyName() {
var str = this.barcodefield.end;
var res = str.substring(0, 2);
if (this.barcodeprefixes[res] == undefined) {
this.agencyName = "Agency not found";
} else {
this.agencyName = this.barcodeprefixes[res];
}
},
},
mounted() {
this.addLine();
}
}
Here is a codepen for you.
Upvotes: 1
Views: 66
Reputation: 1730
There are a couple of problem with this.
First, you have a typo in the barcodefield
data object. You have "star" instead of "start".
Secondly in the showAgency
method you are referencing the this.barcodefield
properties but that doesn't exist.
What you can do is pass the index of the barcodefield to the showAgencyName method, and use that inside the method to get the desired barcodefield from the barcodefields
array.
In your html:
<q-input outlined square dense maxlength="24"
v-model.trim="barcodefield.end" @blur="showAgencyName(index)" ref="bcentry"></q-input>
and the showAgencyName method:
showAgencyName(index) {
const barcodefield = this.barcodefields[index]
var str = barcodefield.end;
var res = str.substring(0, 2);
if (this.barcodeprefixes[res] == undefined) {
this.agencyName = "Agency not found";
} else {
this.agencyName = this.barcodeprefixes[res];
}
}
UPDATE:
There is another problem that I didn't notice at first. The agencyName
is overwritten every time you add a new barcodefield since it is kind of a global value.
I update the Codepen with the simplest solution I could think of. Return the name of the agency from the showAgencyName
and use that to print it on the interface. There are many possible other solutions to this (for example add the name the the barcodefields object in the array).
Here is a working Codepen
Upvotes: 1
Reputation: 1983
There are several things going on here:
First, as Simon points out, don't name loop variables the same thing as a top-level data element. Instead of <div v-for="(barcodefield, index) in barcodefields" :key="index">
, do <div v-for="(item, index) in barcodefields" :key="index">
. Then update all the barcodefield.start
and barcodfield.end
references to item.start
and item.end
.
Then, you need to get each item to have its own agencyName
, instead of all of them referring to the same data.
Update showAgencyName
to this:
showAgencyName(item) {
var str = item.end;
var res = str.substring(0, 2);
if (this.barcodeprefixes[res] == undefined) {
item.agencyName = "Agency not found";
} else {
item.agencyName = this.barcodeprefixes[res];
}
},
Then you can call it like this: @blur="showAgencyName(item)"
And use it in the html like so:
<div v-if="item.agencyName" style="min-height: 40px">
{{ item.agencyName }}
</div>
(And you can get rid of the top-level barcodefield
in the data object, because it's not used anymore.)
Fiddle here: https://jsfiddle.net/ebbishop/7r1pqx9f/
Upvotes: 1
Reputation: 162
{{ getAgencyName(b) }}
instead of {{ agencyName }}
otherwise you will have same agency name for all linesUpvotes: 1