typeahead嵌套的json对象

时间:2015-01-15 20:22:00

标签: json ember.js typeahead.js

我是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时它会出现: 类别:超市, 姓名:CARREFOUR 名称:CAFCO

当我键入字母c时,搜索下拉列表中的输出相同。

任何帮助?

New Jsbin example

1 个答案:

答案 0 :(得分:0)

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

要转到latitude,您需要浏览merchants数组,然后查看branches数组。因为这将跨越多个元素,你将最终得到"阵列数组"类型数据结构,这是很烦人的处理。因此,为了简化这一点,我们可以创建一个简单的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

  

返回数组的副本,删除所有null和undefined元素。

一旦您拥有包含所有必要数据的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')

上面的代码看起来很复杂,但它基本上只返回一组顶级对象&#39;商人陪同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