Angular ng-model&使用嵌套数据与顶层进行过滤

时间:2018-04-11 14:24:23

标签: javascript angular typescript

我的页面上显示的数据列表分为divs。每个div代表我的对象中的数据数组,非常常见。

我正在尝试向我的页面添加一个文本框,我可以在其中过滤掉数据,并且当文本框中输入更多数据时,它会缩小页面上显示的结果。

为此,我在我的ngFor上添加了一个过滤器,如下所示:*ngFor="let x of data | filter: filterString"

我的文字框然后使用ngModel过滤掉这些数据:

<input type="text" class="form-control" placeholder="Filter..." name="ruleFilter" id="ruleFilter" [(ngModel)]="filterString" (keyup)="onFilter($event)">

我遇到的问题是过滤器似乎只处理我对象中的顶层数据。例如,下面的数据是我的ngFor循环中的结果之一。我可以搜索Omaha,因为它位于顶层,并且可以正确过滤掉它。

但是,如果我查找嵌套在Campus内的Attribute之类的内容,则会在过滤器中找不到它,并且不会显示任何结果。

{
  "RuleParentID": "618",
  "RuleVersionID": "18",
  "MappedValue": "1",
  "ProcessingOrder": 1,
  "KeyID": "1",
  "Value": "Omaha",
  "IsRuleRetired": "0",
  "UserImpactCount": "0",
  "Attribute": [
    {
      "AttributeID": "6",
      "AttributeName": "Campus",
      "Operator": {
        "OperatorID": "3",
        "OperatorName": "In List",
        "SqlOperator": "IN"
      },
      "AttributeValue": [
        {
          "AttrValue": "1",
          "Value": "Omaha",
          "IsValueRetired": "0",
          "disabled": "False"
        }
      ]
    },
    {
      "AttributeID": "14",
      "AttributeName": "Grade",
      "Operator": {
        "OperatorID": "1",
        "OperatorName": "Greater Than",
        "SqlOperator": ">"
      },
      "AttributeValue": [
        {
          "AttrValue": "14",
          "Value": "14",
          "IsValueRetired": "0",
          "disabled": "False"
        }
      ]
    }
  ]
}

有没有办法让模型看到我绑定的对象的所有层而不仅仅是顶层(我现在只假设它在做什么)?

更新:以下是我的基本设置的一部分:https://plnkr.co/edit/eywuWmPRseUkmVPbTEOf?p=preview

你会看到顶级属性搜索的数据模型很好,但是当我搜索嵌套的东西时,我没有得到任何结果。

3 个答案:

答案 0 :(得分:0)

如果我理解这个问题,我认为平衡数据会对你有所帮助:

var flattenObject = function(ob) {
    var toReturn = {};

    for (var i in ob) {
        if (!ob.hasOwnProperty(i)) continue;

        if ((typeof ob[i]) == 'object') {
            var flatObject = flattenObject(ob[i]);
            for (var x in flatObject) {
                if (!flatObject.hasOwnProperty(x)) continue;

                toReturn[i + '.' + x] = flatObject[x];
            }
        } else {
            toReturn[i] = ob[i];
        }
    }
    return toReturn;
};

let newData = flattenObject(data);

代码来源:https://gist.github.com/penguinboy/762197

答案 1 :(得分:0)

要达到预期效果,请使用以下选项

1.在变量

下面的组件中
jsonVal:any=JSON; // for using JSON.stringify and indexOf
  1. 使用 * ngIf 从indexOf
  2. 输入中过滤值

        <input type="text" [(ngModel)]="filterString">
        <div *ngFor="let data of result">
          <div *ngIf="jsonVal.stringify(data).indexOf(filterString)!= -1">{{data| json}}</div>
          </div>

    代码示例供参考 - https://stackblitz.com/edit/angular-ht2afv?file=app/app.component.html

    仅仅是为了测试,我添加了另一个带有Campus2和Omaha2的对象

答案 2 :(得分:0)

在对数据的嵌套属性进行过滤时,您可以使用map函数或类似函数。

这将在您的组件中,而不是模板。出于性能原因,Angular团队使用模板中的管道进行过滤是discouraged

相反,我会做这样的事情:

const data = [{//your data}]

let filteredData = [];

data.map(val => {
          if (val.Attribute.filter(name => name.AttributeName === "Foo").length > 0) {
            filteredData.push(val)
          }
        });

我假设你的数据是一个对象数组。

注意我正在改变我的数据对象。为避免这种情况,请执行以下操作:

const data = [{//your original data}]
const dataToFilter = JSON.Parse(JSON.stringify(data))

这将复制您的数据而不引用您的原始对象。如果要清除过滤器,则非常有用。如果您的数据对象包含函数,则无用。

在重新阅读您的问题时,我认为这不是您正在寻找的解决方案,而是一种查看数据中任何位置的方法。为此,您应该按照Zelda7的建议来平整您的数据。另一种方法是扩展过滤方法,以明确过滤所有相关字段。