预输入嵌套 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 时,搜索下拉列表中的输出相同。

有什么帮助吗?

New Jsbin example

最简单的方法(在我看来)是创建一个包含纬度数组的计算 属性。但是我们如何到达那里呢?

要到达 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')

上面,我基本上是用mapByflatten(见上文)和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