预输入嵌套 json 对象
typeahead nested json object
我是 Ember 和 JSON 的新手。我想用 typeahead 库解析下面的 JSON 对象
并通过搜索它们的键来访问嵌套对象值。
我有这个 Json 格式:
return [
{
"id": 1,
"category_name": "Supermarket",
"category_description": "SUPER MARKET",
"image_url": "",
"merchants": [
{
"name": "CARREFOUR",
"id": 12,
"merchant_type_id": 1,
"merchant_type_description": "Gold",
"merchant_redeption_rate": 0.002500,
"image_url": "https://jpg",
"branches": [
{
"id": 123456,
"latitude": 37.939483,
"area": "ΑΓ. ΔΗΜΗΤΡΙΟΣ",
"zip": "12345"
},
{
"id": 4567890,
"longitude": 23.650622,
"area": "ΑΓ. ΙΩΑΝΝΗΣ ΡΕΝΤΗΣ",
"zip": "12345"
}
]
},
{
"name": "CAFCO",
"id": 13,
"merchant_type_id": 3,
"merchant_type_description": "None",
"merchant_redeption_rate": 0.002500,
"image_url": "https:.jpg",
"branches": [
{
"id": 127890,
"latitude": 38.027870,
"area": "ΠΕΡΙΣΤΕΡΙ",
"zip": "12345"
}
]
}
]
},
{
"id": 2,
"category_name": "Πολυκαταστήματα",
"category_description": "ΠΟΛΥΚΑΤΑΣΤΗΜΑ",
"image_url": "",
"merchants": [
{
"name": "AGGELOPOYLOS CHR.",
"id": 15,
"merchant_type_id": 2,
"merchant_type_description": "Silver",
"merchant_redeption_rate": 0.002500,
"image_url": "https://www.nbg.gr/greek/retail/cards/reward-programmes/gonational/PublishingImages/aggelopoulos.jpg",
"branches": [
{
"id": 234780,
"latitude": 35.366118,
"longitude": 24.479461,
"address": "ΕΘΝ. ΜΑΚΑΡΙΟΥ 9 & ΕΛ. ΒΕΝΙΖΕΛΟΥ 1",
"area": "Ν. ΦΑΛΗΡΟ",
"zip": "12345"
}
]
}
]
}
];
-------------------------已更新-------- --------------------
例如,我想使用 typeahead 搜索商家名称,当我们写的搜索字母与商家名称匹配时,它会出现相应的 category_name 和倒序。
示例 -> 当我输入 s 时,它会出现:
类别 : 超市,
名称:家乐福
姓名:CAFCO
当我输入字母 c 时,搜索下拉列表中的输出相同。
有什么帮助吗?
最简单的方法(在我看来)是创建一个包含纬度数组的计算 属性。但是我们如何到达那里呢?
要到达 latitude
,您需要先遍历 merchants
数组,然后再遍历 branches
数组。由于这将跨越多个元素,因此您最终会得到 "array of arrays" 类型的数据结构,这很烦人。因此,为了简化这一点,我们可以创建一个简单的 flatten
函数,如下所示:
flatten: function(origArray){
var newArr = [];
origArray.forEach(function(el) {
el.forEach(function(eachEl){
newArr.push(eachEl);
});
});
return newArr;
},
除了我们上面的函数,Ember 已经为我们提供了许多其他可用于数组的有用函数(参见 here)。其中之一是 mapBy(property)
,它将一个数组转换为另一个数组,只保留我们指定的 属性 的值。
因此,要创建一个 lats
(对于纬度)属性,我们可以这样做:
lats: function(){
var merchantsArr = this.get('model').mapBy('merchants');
merchantsArr = this.flatten(merchantsArr);
var branchesArr = merchantsArr.mapBy('branches');
branchesArr = this.flatten(branchesArr);
return branchesArr.mapBy("latitude").compact();
}.property('model')
上面,我基本上是用mapBy
,flatten
(见上文)和compact
,其中
Returns a copy of the array with all null and undefined elements removed.
一旦您拥有包含所有必要数据的 lats
属性,剩下的就很简单了。
您对组件的调用变为:
{{x-typeahead data=lats name='category_name' selection=myColor}}
注意 lats
而不是 model
您最初传递到组件中。
现在,要在组件中访问 data
属性 的值,您需要
`this.get('data')`
你可以像这样作为 source
传递:
source: substringMatcher(self.get('data'))
工作解决方案here
更新
正在根据您更新的问题更新我的答案。
好的,这变得有点复杂了。您现在需要的对象不止一个 属性 (latitude
)。您需要 category_name
和商家 name
.
除了 mapBy
,它只是从数组中抓取一个 属性,Ember 还有 map
,它可以让你把数组转换成几乎任何你想要的东西想要:
lats: function(){
var merchantsArr = this.get('model').map(function(thing){
var category_name = thing.category_name;
return thing.merchants.map(function(merchant){
return {
"name": merchant.name,
"category": category_name
};
});
});
merchantsArr = this.flatten(merchantsArr);
return merchantsArr;
}.property('model')
上面的代码看起来很复杂,但它基本上只是返回一个包含category_name
的顶级对象的商户数组。由于这是一个数组数组,我们需要将其展平。
然后,在组件内部,我们需要记住,我们不只是传递一个字符串数组,而是传递一个对象数组。因此,我们需要通过对象的属性(名称和类别)来查找匹配项
$.each(strs, function(i, str) {
if (substrRegex.test(str.name) || substrRegex.test(str.category)) {
matches.push(str);
}
});
最后,要实际显示类别和商家名称,您需要告诉 Typeahead 如何执行此操作:
templates: {
suggestion: Handlebars.compile('<p>{{name}} – {{category}}</p>')
}
工作解决方案here
我是 Ember 和 JSON 的新手。我想用 typeahead 库解析下面的 JSON 对象 并通过搜索它们的键来访问嵌套对象值。
我有这个 Json 格式:
return [
{
"id": 1,
"category_name": "Supermarket",
"category_description": "SUPER MARKET",
"image_url": "",
"merchants": [
{
"name": "CARREFOUR",
"id": 12,
"merchant_type_id": 1,
"merchant_type_description": "Gold",
"merchant_redeption_rate": 0.002500,
"image_url": "https://jpg",
"branches": [
{
"id": 123456,
"latitude": 37.939483,
"area": "ΑΓ. ΔΗΜΗΤΡΙΟΣ",
"zip": "12345"
},
{
"id": 4567890,
"longitude": 23.650622,
"area": "ΑΓ. ΙΩΑΝΝΗΣ ΡΕΝΤΗΣ",
"zip": "12345"
}
]
},
{
"name": "CAFCO",
"id": 13,
"merchant_type_id": 3,
"merchant_type_description": "None",
"merchant_redeption_rate": 0.002500,
"image_url": "https:.jpg",
"branches": [
{
"id": 127890,
"latitude": 38.027870,
"area": "ΠΕΡΙΣΤΕΡΙ",
"zip": "12345"
}
]
}
]
},
{
"id": 2,
"category_name": "Πολυκαταστήματα",
"category_description": "ΠΟΛΥΚΑΤΑΣΤΗΜΑ",
"image_url": "",
"merchants": [
{
"name": "AGGELOPOYLOS CHR.",
"id": 15,
"merchant_type_id": 2,
"merchant_type_description": "Silver",
"merchant_redeption_rate": 0.002500,
"image_url": "https://www.nbg.gr/greek/retail/cards/reward-programmes/gonational/PublishingImages/aggelopoulos.jpg",
"branches": [
{
"id": 234780,
"latitude": 35.366118,
"longitude": 24.479461,
"address": "ΕΘΝ. ΜΑΚΑΡΙΟΥ 9 & ΕΛ. ΒΕΝΙΖΕΛΟΥ 1",
"area": "Ν. ΦΑΛΗΡΟ",
"zip": "12345"
}
]
}
]
}
];
-------------------------已更新-------- --------------------
例如,我想使用 typeahead 搜索商家名称,当我们写的搜索字母与商家名称匹配时,它会出现相应的 category_name 和倒序。
示例 -> 当我输入 s 时,它会出现: 类别 : 超市, 名称:家乐福 姓名:CAFCO
当我输入字母 c 时,搜索下拉列表中的输出相同。
有什么帮助吗?
最简单的方法(在我看来)是创建一个包含纬度数组的计算 属性。但是我们如何到达那里呢?
要到达 latitude
,您需要先遍历 merchants
数组,然后再遍历 branches
数组。由于这将跨越多个元素,因此您最终会得到 "array of arrays" 类型的数据结构,这很烦人。因此,为了简化这一点,我们可以创建一个简单的 flatten
函数,如下所示:
flatten: function(origArray){
var newArr = [];
origArray.forEach(function(el) {
el.forEach(function(eachEl){
newArr.push(eachEl);
});
});
return newArr;
},
除了我们上面的函数,Ember 已经为我们提供了许多其他可用于数组的有用函数(参见 here)。其中之一是 mapBy(property)
,它将一个数组转换为另一个数组,只保留我们指定的 属性 的值。
因此,要创建一个 lats
(对于纬度)属性,我们可以这样做:
lats: function(){
var merchantsArr = this.get('model').mapBy('merchants');
merchantsArr = this.flatten(merchantsArr);
var branchesArr = merchantsArr.mapBy('branches');
branchesArr = this.flatten(branchesArr);
return branchesArr.mapBy("latitude").compact();
}.property('model')
上面,我基本上是用mapBy
,flatten
(见上文)和compact
,其中
Returns a copy of the array with all null and undefined elements removed.
一旦您拥有包含所有必要数据的 lats
属性,剩下的就很简单了。
您对组件的调用变为:
{{x-typeahead data=lats name='category_name' selection=myColor}}
注意 lats
而不是 model
您最初传递到组件中。
现在,要在组件中访问 data
属性 的值,您需要
`this.get('data')`
你可以像这样作为 source
传递:
source: substringMatcher(self.get('data'))
工作解决方案here
更新
正在根据您更新的问题更新我的答案。
好的,这变得有点复杂了。您现在需要的对象不止一个 属性 (latitude
)。您需要 category_name
和商家 name
.
除了 mapBy
,它只是从数组中抓取一个 属性,Ember 还有 map
,它可以让你把数组转换成几乎任何你想要的东西想要:
lats: function(){
var merchantsArr = this.get('model').map(function(thing){
var category_name = thing.category_name;
return thing.merchants.map(function(merchant){
return {
"name": merchant.name,
"category": category_name
};
});
});
merchantsArr = this.flatten(merchantsArr);
return merchantsArr;
}.property('model')
上面的代码看起来很复杂,但它基本上只是返回一个包含category_name
的顶级对象的商户数组。由于这是一个数组数组,我们需要将其展平。
然后,在组件内部,我们需要记住,我们不只是传递一个字符串数组,而是传递一个对象数组。因此,我们需要通过对象的属性(名称和类别)来查找匹配项
$.each(strs, function(i, str) {
if (substrRegex.test(str.name) || substrRegex.test(str.category)) {
matches.push(str);
}
});
最后,要实际显示类别和商家名称,您需要告诉 Typeahead 如何执行此操作:
templates: {
suggestion: Handlebars.compile('<p>{{name}} – {{category}}</p>')
}
工作解决方案here