我想获取数据进行编辑时出现vue.js问题,并且出现以下错误:
无法读取未定义的属性'reduce'
但是当我使用console.log
时,数据是正确的。我尝试花更多时间在代码上更改this.$set(this.$data, "form", res.returnsale)
中的fetchRuturn
,然后出现此错误。
<template>
<v-app>
<v-card class="mx-5 my-5">
<div class="teal darken-1">
<v-card-title class="white--text">Edit Return Sale</v-card-title>
</div>
<v-divider></v-divider>
<div class="px-5">
<p class="caption font-italic pt-5">The field labels marked with * are required input fields.</p>
<v-row>
<v-col md="6" cols="12">
<label for="reference_no" class="font-weight-bold">Reference No</label>
<v-text-field solo outlined dense v-model="form.reference_no"></v-text-field>
</v-col>
<v-col md="6" cols="12">
<label class="font-weight-bold">Location*</label>
<v-autocomplete item-value="address" item-text="address" solo outlined dense label="Business Location"
return-object v-model="form.location" :items="locations"></v-autocomplete>
</v-col>
<v-col md="6" cols="12">
<label class="font-weight-bold">Supplier</label>
<v-autocomplete :items="suppliers" item-text="name" item-value="name" solo outlined dense return-object
v-model="form.supplier" label="Select Supplier"></v-autocomplete>
</v-col>
<v-col md="6" cols="12">
<label class="font-weight-bold">Account</label>
<v-autocomplete :items="accounts" item-text="name" item-value="name" solo outlined dense return-object
v-model="form.account" label="Select Account"></v-autocomplete>
</v-col>
<v-col cols="12">
<label class="font-weight-bold">Select Product</label>
<div>
<v-autocomplete dense solo item-text="name" item-value="name" return-object :items="products"
@input="addTocart"></v-autocomplete>
</div>
</v-col>
</v-row>
<div>
<label class="font-weight-bold mb-3">Product Table</label>
<table class="tableReturn">
<thead>
<tr class="tableReturn--header">
<td>Name</td>
<td>Code</td>
<td>Quantity</td>
<td>Unit Price</td>
<td>Discount</td>
<td>Total</td>
<td>Actions</td>
</tr>
</thead>
<tbody>
<tr class="tableReturn--td" v-for="(item, index) in form.items" :key="index">
<td>{{item.name}}</td>
<td>{{item.code}}</td>
<td>
<input type="number" class="table-quantity" v-model="form.items[index].quantity" />
</td>
<td>
<input type="number" class="table-quantity" v-model="form.items[index].unit_price"
placeholder="0.00" />
</td>
<td>
<input type="number" class="table-quantity" v-model="form.items[index].discount" placeholder="0.00" />
</td>
<td>USD {{ discountedPrice(item) | formatMoney }}</td>
<td>
<v-btn small color="red" outlined @click="removeItem(index)">
<v-icon>mdi-delete</v-icon>
</v-btn>
</td>
</tr>
<tr>
<td class="py-5" colspan="2">Total</td>
<td colspan="3">{{ Qty }}</td>
<td>USD {{ Total | formatMoney }}</td>
</tr>
</tbody>
</table>
</div>
<v-row>
<v-col md="6" cols="12">
<div class="d-flex flex-column mb-5">
<label for="" class="font-weight-bold">Return Note</label>
<textarea cols="30" rows="5" class="textarea" v-model="form.return_des"></textarea>
</div>
</v-col>
<v-col md="6" cols="12">
<div class="d-flex flex-column mb-5">
<label for="" class="font-weight-bold">Staff Note</label>
<textarea cols="30" rows="5" class="textarea" v-model="form.staff_des"></textarea>
</div>
</v-col>
</v-row>
</div>
<v-btn @click.prevent="updateReturn" class="blue mx-5 darken-2 mb-5 grey--text text--lighten-4">
<v-icon>mdi-check</v-icon>Update
</v-btn>
</v-card>
</v-app>
</template>
<script>
import Vue from "vue";
let numeral = require('numeral');
Vue.filter('formatMoney', function (value) {
return numeral(value).format('00,00.00')
});
export default {
name: "editReturn",
created() {
this.fetchReturn();
this.fetchLocation();
this.fetchSupplier();
this.fetchAccount();
this.fetchProduct();
},
data() {
return {
form: {
items: []
},
suppliers: [],
locations: [],
products: [],
returnsale: [],
accounts: []
};
},
computed: {
Qty() {
return this.form.items.reduce((total, item) => {
return total + Number(item.quantity);
}, 0);
},
Total() {
return this.form.items.reduce((total, item) => {
let subtotal = (item.unit_price - (item.unit_price * item.discount) / 100) *
item.quantity
return total + subtotal;
}, 0);
}
},
methods: {
discountedPrice(product) {
return (
(product.unit_price -
(product.unit_price * product.discount) / 100) *
product.quantity
);
},
fetchLocation() {
this.$axios.$get(`api/location`)
.then(res => {
// this.locations = res.locations.data;
this.$set(this.$data, "locations", res.locations.data);
console.log(res);
})
.catch(err => {
console.log(err.response);
});
},
fetchSupplier() {
this.$axios.$get(`api/supplier`)
.then(res => {
this.$set(this.$data, "suppliers", res.suppliers.data);
console.log(res);
})
.catch(err => {
console.log(err.response);
});
},
fetchAccount() {
this.$axios.$get(`api/account`)
.then(res => {
this.$set(this.$data, "accounts", res.accounts);
console.log(res)
})
.catch(err => {
console.log(err.response);
});
},
fetchProduct() {
this.$axios
.$get(`/api/product`)
.then(res => {
this.$set(this.$data, "products", res.products.data);
console.log(res);
})
.catch(err => {
console.log(err);
});
},
fetchReturn() {
this.$axios
.$get(`api/return-sale/` + this.$route.params.id)
.then(res => {
this.$set(this.$data, "form", res.returnsale);
console.log(res);
for (let i in this.form.items) {
Vue.set(this.form.items[i], 'quantity', this.form.items[i].pivot.quantity);
Vue.set(this.form.items[i], 'unit_price', this.form.items[i].pivot.unit_price);
Vue.set(this.form.items[i], 'discount', this.form.items[i].pivot.discount);
}
})
.catch(err => {
console.log(res.response);
});
},
updateReturn() {
this.$axios
.$patch(`api/return-sale/` + this.form.id, {
location: this.form.location,
products: this.form.products,
supplier: this.form.supplier,
account: this.form.account,
return_des: this.form.return_des,
staff_des: this.form.staff_des,
})
.then(res => {
this.returnsale = res.data;
// this.$set(this.$data, "returnsale", res.data);
this.$set(this.$data, "returnsale", res.returnsale);
this.$router.push(`/return/return-sale/view`);
console.log(res);
})
.catch(err => {
console.log(err.response);
});
},
addTocart(item) {
if (this.form.items.includes(item)) {
alert("already there");
} else {
this.form.items.push(item);
}
Vue.set(item, 'quantity', 1);
Vue.set(item, 'discount', 1);
},
removeItem(index) {
this.form.items.splice(index, 1);
}
}
};
</script>
<style lang="scss">
.textarea {
border: 1px solid rgba(0, 0, 0, 0.125);
outline: 1px solid #461577;
}
.tableReturn {
width: 100%;
margin-top: 10px;
border-collapse: collapse;
&--header {
font-weight: 500;
text-align: left;
border-bottom: 1px solid rgba(0, 0, 0, 0.125);
}
&--td {
border-bottom: 1px solid rgba(0, 0, 0, 0.125);
}
}
.table-quantity {
border: 1px solid rgba(0, 0, 0, 0.125);
padding: 5px 10px 5px 10px;
margin-top: 5px;
margin-bottom: 5px;
}
</style>
答案 0 :(得分:1)
尝试一下
我添加了一张支票if (this.form.hasOwnProperty("items"))
如果形式有价值,那么只有它才能发挥作用
<template>
<v-app>
<v-card class="mx-5 my-5">
<div class="teal darken-1">
<v-card-title class="white--text">Edit Return Sale</v-card-title>
</div>
<v-divider></v-divider>
<div class="px-5">
<p
class="caption font-italic pt-5"
>The field labels marked with * are required input fields.</p>
<v-row>
<v-col md="6" cols="12">
<label for="reference_no" class="font-weight-bold">Reference No</label>
<v-text-field solo outlined dense v-model="form.reference_no"></v-text-field>
</v-col>
<v-col md="6" cols="12">
<label class="font-weight-bold">Location*</label>
<v-autocomplete
item-value="address"
item-text="address"
solo
outlined
dense
label="Business Location"
return-object
v-model="form.location"
:items="locations"
></v-autocomplete>
</v-col>
<v-col md="6" cols="12">
<label class="font-weight-bold">Supplier</label>
<v-autocomplete
:items="suppliers"
item-text="name"
item-value="name"
solo
outlined
dense
return-object
v-model="form.supplier"
label="Select Supplier"
></v-autocomplete>
</v-col>
<v-col md="6" cols="12">
<label class="font-weight-bold">Account</label>
<v-autocomplete
:items="accounts"
item-text="name"
item-value="name"
solo
outlined
dense
return-object
v-model="form.account"
label="Select Account"
></v-autocomplete>
</v-col>
<v-col cols="12">
<label class="font-weight-bold">Select Product</label>
<div>
<v-autocomplete
dense
solo
item-text="name"
item-value="name"
return-object
:items="products"
@input="addTocart"
></v-autocomplete>
</div>
</v-col>
</v-row>
<div>
<label class="font-weight-bold mb-3">Product Table</label>
<table class="tableReturn">
<thead>
<tr class="tableReturn--header">
<td>Name</td>
<td>Code</td>
<td>Quantity</td>
<td>Unit Price</td>
<td>Discount</td>
<td>Total</td>
<td>Actions</td>
</tr>
</thead>
<tbody>
<tr class="tableReturn--td" v-for="(item, index) in form.items" :key="index">
<td>{{item.name}}</td>
<td>{{item.code}}</td>
<td>
<input type="number" class="table-quantity" v-model="form.items[index].quantity" />
</td>
<td>
<input
type="number"
class="table-quantity"
v-model="form.items[index].unit_price"
placeholder="0.00"
/>
</td>
<td>
<input
type="number"
class="table-quantity"
v-model="form.items[index].discount"
placeholder="0.00"
/>
</td>
<td>USD {{ discountedPrice(item) | formatMoney }}</td>
<td>
<v-btn small color="red" outlined @click="removeItem(index)">
<v-icon>mdi-delete</v-icon>
</v-btn>
</td>
</tr>
<tr>
<td class="py-5" colspan="2">Total</td>
<td colspan="3">{{ Qty }}</td>
<td>USD {{ Total | formatMoney }}</td>
</tr>
</tbody>
</table>
</div>
<v-row>
<v-col md="6" cols="12">
<div class="d-flex flex-column mb-5">
<label for class="font-weight-bold">Return Note</label>
<textarea cols="30" rows="5" class="textarea" v-model="form.return_des"></textarea>
</div>
</v-col>
<v-col md="6" cols="12">
<div class="d-flex flex-column mb-5">
<label for class="font-weight-bold">Staff Note</label>
<textarea cols="30" rows="5" class="textarea" v-model="form.staff_des"></textarea>
</div>
</v-col>
</v-row>
</div>
<v-btn
@click.prevent="updateReturn"
class="blue mx-5 darken-2 mb-5 grey--text text--lighten-4"
>
<v-icon>mdi-check</v-icon>Update
</v-btn>
</v-card>
</v-app>
</template>
<script>
import Vue from "vue";
let numeral = require("numeral");
Vue.filter("formatMoney", function(value) {
return numeral(value).format("00,00.00");
});
export default {
name: "editReturn",
created() {
this.fetchReturn();
this.fetchLocation();
this.fetchSupplier();
this.fetchAccount();
this.fetchProduct();
},
data() {
return {
form: {
items: []
},
suppliers: [],
locations: [],
products: [],
returnsale: [],
accounts: []
};
},
computed: {
Qty() {
if (this.form.hasOwnProperty("items")) {
return this.form.items.reduce((total, item) => {
return total + Number(item.quantity);
}, 0);
}
},
Total() {
if (this.form.hasOwnProperty("items")) {
return this.form.items.reduce((total, item) => {
let subtotal =
(item.unit_price - (item.unit_price * item.discount) / 100) *
item.quantity;
return total + subtotal;
}, 0);
}
}
},
methods: {
discountedPrice(product) {
return (
(product.unit_price - (product.unit_price * product.discount) / 100) *
product.quantity
);
},
fetchLocation() {
this.$axios
.$get(`api/location`)
.then(res => {
// this.locations = res.locations.data;
this.$set(this.$data, "locations", res.locations.data);
console.log(res);
})
.catch(err => {
console.log(err.response);
});
},
fetchSupplier() {
this.$axios
.$get(`api/supplier`)
.then(res => {
this.$set(this.$data, "suppliers", res.suppliers.data);
console.log(res);
})
.catch(err => {
console.log(err.response);
});
},
fetchAccount() {
this.$axios
.$get(`api/account`)
.then(res => {
this.$set(this.$data, "accounts", res.accounts);
console.log(res);
})
.catch(err => {
console.log(err.response);
});
},
fetchProduct() {
this.$axios
.$get(`/api/product`)
.then(res => {
this.$set(this.$data, "products", res.products.data);
console.log(res);
})
.catch(err => {
console.log(err);
});
},
fetchReturn() {
this.$axios
.$get(`api/return-sale/` + this.$route.params.id)
.then(res => {
this.$set(this.$data, "form", res.returnsale);
console.log(res);
for (let i in this.form.items) {
Vue.set(
this.form.items[i],
"quantity",
this.form.items[i].pivot.quantity
);
Vue.set(
this.form.items[i],
"unit_price",
this.form.items[i].pivot.unit_price
);
Vue.set(
this.form.items[i],
"discount",
this.form.items[i].pivot.discount
);
}
})
.catch(err => {
console.log(res.response);
});
},
updateReturn() {
this.$axios
.$patch(`api/return-sale/` + this.form.id, {
location: this.form.location,
products: this.form.products,
supplier: this.form.supplier,
account: this.form.account,
return_des: this.form.return_des,
staff_des: this.form.staff_des
})
.then(res => {
this.returnsale = res.data;
// this.$set(this.$data, "returnsale", res.data);
this.$set(this.$data, "returnsale", res.returnsale);
this.$router.push(`/return/return-sale/view`);
console.log(res);
})
.catch(err => {
console.log(err.response);
});
},
addTocart(item) {
if (this.form.items.includes(item)) {
alert("already there");
} else {
this.form.items.push(item);
}
Vue.set(item, "quantity", 1);
Vue.set(item, "discount", 1);
},
removeItem(index) {
this.form.items.splice(index, 1);
}
}
};
</script>
<style lang="scss">
.textarea {
border: 1px solid rgba(0, 0, 0, 0.125);
outline: 1px solid #461577;
}
.tableReturn {
width: 100%;
margin-top: 10px;
border-collapse: collapse;
&--header {
font-weight: 500;
text-align: left;
border-bottom: 1px solid rgba(0, 0, 0, 0.125);
}
&--td {
border-bottom: 1px solid rgba(0, 0, 0, 0.125);
}
}
.table-quantity {
border: 1px solid rgba(0, 0, 0, 0.125);
padding: 5px 10px 5px 10px;
margin-top: 5px;
margin-bottom: 5px;
}
</style>