使用 VueJS 在 table 的输入中传递来自 Element UI 自动完成的值
Pass values from Element UI autocomplete in the inputs of a table using VueJS
我正在尝试使用 元素 UI 创建发票表单。我添加了一个自动完成功能,它从 loadAll 数组中获取数据。单击 add 按钮并从自动完成中选择 item_name 后,我想传递关联的 selling_price in the price input using handleSelect method and set the calculated the amount in the amount 使用 amountfn 方法输入,可以通过 onChange 更新 Qty 输入的值。
另外,当 item_name 已经添加到名称 input
中时,防止从自动完成部分选择重复的 item_name 会非常好
这是我的代码
<template>
<el-form
ref="updateForm"
:model="cart"
status-icon
label-width="100px"
@keydown.enter.native="updateContact"
>
<el-table :data="cart.items" style="width: 100%">
<el-table-column label="Name">
<template slot-scope="scope">
<el-autocomplete
class="inline-input"
v-model="scope.row.item_name"
value-key="item_name"
:fetch-suggestions="querySearch"
placeholder="Please Input"
:trigger-on-focus="false"
@select="handleSelect"
></el-autocomplete>
</template>
</el-table-column>
<el-table-column label="QTY">
<template slot-scope="scope">
<el-input v-model="scope.row.qty"></el-input>
</template>
</el-table-column>
<el-table-column label="Price">
<template slot-scope="scope">
<el-input v-model="scope.row.price"></el-input>
</template>
</el-table-column>
<el-table-column label="Amount">
<template slot-scope="scope">
<el-input v-model="scope.row.total" value="amountfn" disabled></el-input>
</template>
</el-table-column>
<el-table-column>
<template slot-scope="scope">
<el-button type="danger" @click="removeLine(scope.$index)">Del</el-button>
</template>
</el-table-column>
</el-table>
<el-form-item>
<el-button @click="addLine">Add</el-button>
</el-form-item>
<el-row>
<el-col :span="6" :offset="14">Sub Total {{subTotal}}</el-col>
<el-col :span="6" :offset="14">
<el-form-item label="Discount" prop>
<el-input placeholder v-model="cart.discount"></el-input>
</el-form-item>
</el-col>
<el-col :span="6" :offset="14">Grand total {{grandTotal}}</el-col>
</el-row>
</el-form>
</template>
<script>
export default {
data() {
return {
cart: {
items: [],
discount: 0
},
links: []
};
},
methods: {
removeLine(item) {
if (item !== -1) {
this.cart.items.splice(item, 1);
}
},
addLine() {
this.cart.items.push({
item_name: "",
qty: 1,
price: 0,
total: 0
});
},
querySearch(queryString, cb) {
var links = this.links;
var results = queryString
? links.filter(this.createFilter(queryString))
: links;
// call callback function to return suggestions
cb(results);
},
createFilter(queryString) {
return link => {
return (
link.item_name.toLowerCase().indexOf(queryString.toLowerCase()) === 0
);
};
},
loadAll() {
return [
{
id: 2,
upc_ean_isbn: "102",
item_name: "Lucy Olive Oil",
size: "150 ml",
description: "na",
avatar: "no-foto.png",
cost_price: "110.00",
selling_price: "130.00",
quantity: 30,
type: 1,
created_at: "2019-07-05 21:20:10",
updated_at: "2019-07-06 10:41:09"
},
{
id: 8,
upc_ean_isbn: "23001",
item_name: "Pen Desk",
size: "6 inch",
description: "",
avatar: "no photos",
cost_price: "300.00",
selling_price: "350.00",
quantity: 5,
type: 1,
created_at: "2019-10-25 14:42:07",
updated_at: "2019-10-25 14:42:07"
},
{
id: 9,
upc_ean_isbn: "789",
item_name: "Ink",
size: "10 mL",
description: "NA",
avatar: "no photos",
cost_price: "40.00",
selling_price: "60.00",
quantity: 17,
type: 1,
created_at: "2019-10-25 18:22:23",
updated_at: "2019-10-25 18:22:23"
},
{
id: 10,
upc_ean_isbn: "2001",
item_name: "Phone",
size: "na",
description: "na",
avatar: "no photos",
cost_price: "12000.00",
selling_price: "14000.00",
quantity: 5,
type: 1,
created_at: "2019-10-25 18:23:31",
updated_at: "2019-10-25 18:23:31"
},
{
id: 11,
upc_ean_isbn: "999",
item_name: "Tasty tea",
size: "100 g",
description: "",
avatar: "no photos",
cost_price: "30.00",
selling_price: "40.00",
quantity: 30,
type: 1,
created_at: "2019-10-25 18:55:39",
updated_at: "2019-10-25 18:55:39"
}
];
},
handleSelect(item) {
this.cart.items.item_name = item.item_name;
this.cart.items.price = item.selling_price;
console.log("this", this.cart.items);
console.log("that", item);
}
},
mounted() {
this.links = this.loadAll();
},
computed: {
subTotal: function() {
return this.cart.items.reduce(function(carry, item) {
return carry + parseFloat(item.qty) * parseFloat(item.price);
}, 0);
},
grandTotal: function() {
return this.subTotal - parseFloat(this.cart.discount);
},
amountfn: function() {
return this.cart.items.reduce(function(item) {
return parseFloat(item.qty) * parseFloat(item.price);
}, 0);
},
}
};
</script>
这是我的 jsfiddle
https://jsfiddle.net/coolr/87a2hjv0/7/
谢谢
您的问题与您不知道要更新 handleSelect
中的哪一行有关。由于您无法为 handleSelect 方法提供额外的参数,因此您可以通过在 auto-complete
获得焦点时设置 currentItem
来做到这一点。
所以首先是更新自动完成(添加@focus
,还将v-model
更改为value
,我认为这样更好用):
<el-autocomplete
class="inline-input"
:value="scope.row.item_name"
value-key="item_name"
:fetch-suggestions="querySearch"
placeholder=""
:trigger-on-focus="false"
@focus="setCurrentItem(scope.row)"
@select="handleSelect"
></el-autocomplete>
在 JS 中更新您的 data/methods:
data() {
return {
currentItem: null,
// other already existing data
};
},
methods: {
// other already existing methods
setCurrentItem(item) {
this.currentItem = item
},
handleSelect(item) {
this.currentItem.item_name = item.item_name;
this.currentItem.price = item.selling_price;
}
}
对于唯一值,您必须创建一个计算值,其中 returns 除了已使用的值之外的所有值
要更新一行的价格,您可以通过两种不同的方式执行此操作(无论哪种方式都可以删除 amountfn 方法):
更改时,但仅当字段失去焦点时才会触发操作
<el-input v-model="scope.row.price" @change="updateTotal(scope.row)"></el-input>
updateTotal(item) {
item.total = item.price * item.qty
},
使用深度监视,立即执行更新
watch: {
'cart.items' : {
deep: true,
handler: (items) => {
items.forEach(element => element.total = element.price * element.qty)
}
}
}
我正在尝试使用 元素 UI 创建发票表单。我添加了一个自动完成功能,它从 loadAll 数组中获取数据。单击 add 按钮并从自动完成中选择 item_name 后,我想传递关联的 selling_price in the price input using handleSelect method and set the calculated the amount in the amount 使用 amountfn 方法输入,可以通过 onChange 更新 Qty 输入的值。
另外,当 item_name 已经添加到名称 input
中时,防止从自动完成部分选择重复的 item_name 会非常好这是我的代码
<template>
<el-form
ref="updateForm"
:model="cart"
status-icon
label-width="100px"
@keydown.enter.native="updateContact"
>
<el-table :data="cart.items" style="width: 100%">
<el-table-column label="Name">
<template slot-scope="scope">
<el-autocomplete
class="inline-input"
v-model="scope.row.item_name"
value-key="item_name"
:fetch-suggestions="querySearch"
placeholder="Please Input"
:trigger-on-focus="false"
@select="handleSelect"
></el-autocomplete>
</template>
</el-table-column>
<el-table-column label="QTY">
<template slot-scope="scope">
<el-input v-model="scope.row.qty"></el-input>
</template>
</el-table-column>
<el-table-column label="Price">
<template slot-scope="scope">
<el-input v-model="scope.row.price"></el-input>
</template>
</el-table-column>
<el-table-column label="Amount">
<template slot-scope="scope">
<el-input v-model="scope.row.total" value="amountfn" disabled></el-input>
</template>
</el-table-column>
<el-table-column>
<template slot-scope="scope">
<el-button type="danger" @click="removeLine(scope.$index)">Del</el-button>
</template>
</el-table-column>
</el-table>
<el-form-item>
<el-button @click="addLine">Add</el-button>
</el-form-item>
<el-row>
<el-col :span="6" :offset="14">Sub Total {{subTotal}}</el-col>
<el-col :span="6" :offset="14">
<el-form-item label="Discount" prop>
<el-input placeholder v-model="cart.discount"></el-input>
</el-form-item>
</el-col>
<el-col :span="6" :offset="14">Grand total {{grandTotal}}</el-col>
</el-row>
</el-form>
</template>
<script>
export default {
data() {
return {
cart: {
items: [],
discount: 0
},
links: []
};
},
methods: {
removeLine(item) {
if (item !== -1) {
this.cart.items.splice(item, 1);
}
},
addLine() {
this.cart.items.push({
item_name: "",
qty: 1,
price: 0,
total: 0
});
},
querySearch(queryString, cb) {
var links = this.links;
var results = queryString
? links.filter(this.createFilter(queryString))
: links;
// call callback function to return suggestions
cb(results);
},
createFilter(queryString) {
return link => {
return (
link.item_name.toLowerCase().indexOf(queryString.toLowerCase()) === 0
);
};
},
loadAll() {
return [
{
id: 2,
upc_ean_isbn: "102",
item_name: "Lucy Olive Oil",
size: "150 ml",
description: "na",
avatar: "no-foto.png",
cost_price: "110.00",
selling_price: "130.00",
quantity: 30,
type: 1,
created_at: "2019-07-05 21:20:10",
updated_at: "2019-07-06 10:41:09"
},
{
id: 8,
upc_ean_isbn: "23001",
item_name: "Pen Desk",
size: "6 inch",
description: "",
avatar: "no photos",
cost_price: "300.00",
selling_price: "350.00",
quantity: 5,
type: 1,
created_at: "2019-10-25 14:42:07",
updated_at: "2019-10-25 14:42:07"
},
{
id: 9,
upc_ean_isbn: "789",
item_name: "Ink",
size: "10 mL",
description: "NA",
avatar: "no photos",
cost_price: "40.00",
selling_price: "60.00",
quantity: 17,
type: 1,
created_at: "2019-10-25 18:22:23",
updated_at: "2019-10-25 18:22:23"
},
{
id: 10,
upc_ean_isbn: "2001",
item_name: "Phone",
size: "na",
description: "na",
avatar: "no photos",
cost_price: "12000.00",
selling_price: "14000.00",
quantity: 5,
type: 1,
created_at: "2019-10-25 18:23:31",
updated_at: "2019-10-25 18:23:31"
},
{
id: 11,
upc_ean_isbn: "999",
item_name: "Tasty tea",
size: "100 g",
description: "",
avatar: "no photos",
cost_price: "30.00",
selling_price: "40.00",
quantity: 30,
type: 1,
created_at: "2019-10-25 18:55:39",
updated_at: "2019-10-25 18:55:39"
}
];
},
handleSelect(item) {
this.cart.items.item_name = item.item_name;
this.cart.items.price = item.selling_price;
console.log("this", this.cart.items);
console.log("that", item);
}
},
mounted() {
this.links = this.loadAll();
},
computed: {
subTotal: function() {
return this.cart.items.reduce(function(carry, item) {
return carry + parseFloat(item.qty) * parseFloat(item.price);
}, 0);
},
grandTotal: function() {
return this.subTotal - parseFloat(this.cart.discount);
},
amountfn: function() {
return this.cart.items.reduce(function(item) {
return parseFloat(item.qty) * parseFloat(item.price);
}, 0);
},
}
};
</script>
这是我的 jsfiddle
https://jsfiddle.net/coolr/87a2hjv0/7/
谢谢
您的问题与您不知道要更新 handleSelect
中的哪一行有关。由于您无法为 handleSelect 方法提供额外的参数,因此您可以通过在 auto-complete
获得焦点时设置 currentItem
来做到这一点。
所以首先是更新自动完成(添加@focus
,还将v-model
更改为value
,我认为这样更好用):
<el-autocomplete
class="inline-input"
:value="scope.row.item_name"
value-key="item_name"
:fetch-suggestions="querySearch"
placeholder=""
:trigger-on-focus="false"
@focus="setCurrentItem(scope.row)"
@select="handleSelect"
></el-autocomplete>
在 JS 中更新您的 data/methods:
data() {
return {
currentItem: null,
// other already existing data
};
},
methods: {
// other already existing methods
setCurrentItem(item) {
this.currentItem = item
},
handleSelect(item) {
this.currentItem.item_name = item.item_name;
this.currentItem.price = item.selling_price;
}
}
对于唯一值,您必须创建一个计算值,其中 returns 除了已使用的值之外的所有值
要更新一行的价格,您可以通过两种不同的方式执行此操作(无论哪种方式都可以删除 amountfn 方法):
更改时,但仅当字段失去焦点时才会触发操作
<el-input v-model="scope.row.price" @change="updateTotal(scope.row)"></el-input> updateTotal(item) { item.total = item.price * item.qty },
使用深度监视,立即执行更新
watch: { 'cart.items' : { deep: true, handler: (items) => { items.forEach(element => element.total = element.price * element.qty) } } }