如何将对象数组传递给 material vue 自动完成
How to pass array of objects to material vue autocomplete
背景
我正在将对象数组传递给 material 自动完成,可以找到 here。
当我第一次 select 列表中的一个项目时它会抛出错误,然后如果我再次单击该项目它会按预期 select 进行。每次我单击自动完成中的项目时,都会重复相同的过程。
示例错误
[Vue warn]: Error in event handler for "input": "TypeError: Cannot
read property 'constructor' of undefined"
示例代码
<template>
<md-autocomplete
v-model="customer"
:md-options="customers"
@md-changed="getCustomers"
@md-opened="getCustomers"
@md-selected="getSelected"
>
</md-autocomplete>
</template>
<script>
data: () => ({
customers: [],
customer: "", // I also tried making this a {}
}),
methods: {
getCustomers(searchTerm) {
this.customers = new Promise(resolve => {
if (!searchTerm) {
resolve(this.GET_CUSTOMERS);
} else {
const term = searchTerm.toLowerCase();
this.customers = this.GET_CUSTOMERS.filter(({ email }) => {
email.toLowerCase().includes(term);
});
resolve(this.customers);
}
});
},
getSelected() {
console.log(this.customer);
},
}
</script>
数据示例
GET_CUSOTMERS: [
{ client_id: 1, email: "example@example.com" },
{ client_id: 2, email: "example@example.com" }
];
问题
这个错误是什么意思,我该如何解决?我读到 angular 使用 material 的自动完成时存在一个错误,几年前通过这个错误,但我乐观地认为这是目前可以修复的,而不是 material 的错误看。
排除错误
根据 MdAutocomplete
的 input
-handler 源代码,searchTerm
在您的情况下是 undefined
(因此有关访问 constructor
的错误 undefined
):
// MdAutocomplete.vue: onInput()
if (this.searchTerm.constructor.toString().match(/function (\w*)/)[1].toLowerCase() !== 'inputevent') {
^^^^^^^^^^
而 searchTerm
通常是 equal to its value
prop:
data () {
return {
searchTerm: this.value,
//...
}
},
watch: {
value (val) {
this.searchTerm = val
},
//...
},
...除非项目是 selected:
selectItem (item, $event) {
const content = $event.target.textContent.trim()
this.searchTerm = content
//...
}
所以当错误发生时,很可能 MdAutocomplete
的 value
不知何故 undefined
(来自你的 v-model
),导致 searchTerm
也就是undefined
。当你 select 一个项目时, searchTerm
被重置为 selection 的文本内容,并且不会发生错误。
我无法使用 OP 中的代码片段重现那些确切的症状,但出现了看似无关的错误:demo。也许问题缺少重现问题的重要细节。
为 md-autocomplete 选项使用对象数组
md-options
(即此处的 this.customers
)承诺必须 return 一个字符串数组,因此您必须将对象数组转换为预期格式(使用 Array.prototype.map
):
this.customers = new Promise(resolve => {
if (!searchTerm) {
resolve(GET_CUSTOMERS.map(x => x.email)); // <-- map to `email` property
} else {
const term = searchTerm.toLowerCase();
this.customers = GET_CUSTOMERS.filter(/*...*/).map(x => x.email); // <-- map to `email` property
resolve(this.customers);
}
}
Array.prototype.filter
回调必须 return 布尔值才能进行任何过滤。以下arrow function,用作回调,return没什么:
GET_CUSTOMERS.filter(({ email }) => {
email.toLowerCase().includes(term);
});
您可以删除箭头函数的括号:
GET_CUSTOMERS.filter(({ email }) => email.toLowerCase().includes(term));
或使用 return
语句:
GET_CUSTOMERS.filter(({ email }) => {
return email.toLowerCase().includes(term);
});
背景
我正在将对象数组传递给 material 自动完成,可以找到 here。
当我第一次 select 列表中的一个项目时它会抛出错误,然后如果我再次单击该项目它会按预期 select 进行。每次我单击自动完成中的项目时,都会重复相同的过程。
示例错误
[Vue warn]: Error in event handler for "input": "TypeError: Cannot read property 'constructor' of undefined"
示例代码
<template>
<md-autocomplete
v-model="customer"
:md-options="customers"
@md-changed="getCustomers"
@md-opened="getCustomers"
@md-selected="getSelected"
>
</md-autocomplete>
</template>
<script>
data: () => ({
customers: [],
customer: "", // I also tried making this a {}
}),
methods: {
getCustomers(searchTerm) {
this.customers = new Promise(resolve => {
if (!searchTerm) {
resolve(this.GET_CUSTOMERS);
} else {
const term = searchTerm.toLowerCase();
this.customers = this.GET_CUSTOMERS.filter(({ email }) => {
email.toLowerCase().includes(term);
});
resolve(this.customers);
}
});
},
getSelected() {
console.log(this.customer);
},
}
</script>
数据示例
GET_CUSOTMERS: [
{ client_id: 1, email: "example@example.com" },
{ client_id: 2, email: "example@example.com" }
];
问题
这个错误是什么意思,我该如何解决?我读到 angular 使用 material 的自动完成时存在一个错误,几年前通过这个错误,但我乐观地认为这是目前可以修复的,而不是 material 的错误看。
排除错误
根据 MdAutocomplete
的 input
-handler 源代码,searchTerm
在您的情况下是 undefined
(因此有关访问 constructor
的错误 undefined
):
// MdAutocomplete.vue: onInput()
if (this.searchTerm.constructor.toString().match(/function (\w*)/)[1].toLowerCase() !== 'inputevent') {
^^^^^^^^^^
而 searchTerm
通常是 equal to its value
prop:
data () {
return {
searchTerm: this.value,
//...
}
},
watch: {
value (val) {
this.searchTerm = val
},
//...
},
...除非项目是 selected:
selectItem (item, $event) {
const content = $event.target.textContent.trim()
this.searchTerm = content
//...
}
所以当错误发生时,很可能 MdAutocomplete
的 value
不知何故 undefined
(来自你的 v-model
),导致 searchTerm
也就是undefined
。当你 select 一个项目时, searchTerm
被重置为 selection 的文本内容,并且不会发生错误。
我无法使用 OP 中的代码片段重现那些确切的症状,但出现了看似无关的错误:demo。也许问题缺少重现问题的重要细节。
为 md-autocomplete 选项使用对象数组
md-options
(即此处的this.customers
)承诺必须 return 一个字符串数组,因此您必须将对象数组转换为预期格式(使用Array.prototype.map
):this.customers = new Promise(resolve => { if (!searchTerm) { resolve(GET_CUSTOMERS.map(x => x.email)); // <-- map to `email` property } else { const term = searchTerm.toLowerCase(); this.customers = GET_CUSTOMERS.filter(/*...*/).map(x => x.email); // <-- map to `email` property resolve(this.customers); } }
Array.prototype.filter
回调必须 return 布尔值才能进行任何过滤。以下arrow function,用作回调,return没什么:GET_CUSTOMERS.filter(({ email }) => { email.toLowerCase().includes(term); });
您可以删除箭头函数的括号:
GET_CUSTOMERS.filter(({ email }) => email.toLowerCase().includes(term));
或使用
return
语句:GET_CUSTOMERS.filter(({ email }) => { return email.toLowerCase().includes(term); });