1

我有一个应用程序,可以在其中显示带有 AngularJS 的项目列表。我正在尝试在此列表上进行简单搜索,但它会搜索该项目内的所有内容。一个项目的例子:

{
    id: 283727893,
    name: 'Item A',
    parent: {
        id: 239495838,
        name: 'Item B'
    },
    user: 'User C'
}

在列表中我只写了根项目的名称,所以parent.name不会出现。

问题

但是,如果我使用 AngularJS 过滤器按“项目 B”进行搜索,它仍然会出现,因为内部属性具有此字符串。

我试过的

我已经放置了一个对象引用,如下所示(val输入的文本在哪里):

vm.searchObj = {
    name: val,
    user: val
};

然后,在我的 DOM 上:

<li data-ng-repeat="[...] | filter: Ctrl.searchObj | orderBy: Ctrl.orderBy">
...
</li>

但是,这适用于条件 AND,所以它只显示如果两者都有,name并且userval

我需要的

我想获取输入文本并进行搜索以根据给定的对象属性(复数形式)过滤此列表。

所以,在这个例子中,如果我写“项目 A”或“用户 C”(或者只是“A”或只是“C”等等),这个项目应该出现,但如果我写“B”,则不会出现,因为没有nameuser有这封信。

在这种情况下,我需要它来获取参考对象,Ctrl.searchObj并检查对象的任何给定属性是否包含val在过滤对象的相同结构中。

当然,这应该在对象的更深层次上起作用,所以我可以定义searchObj如下,并且仍然能够得到过滤后的对象内部是否具有该结构:

vm.searchObj = {
    parent: {
        name: 'Item'
    }
};

在这种情况下,它应该显示其parent.name属性包含单词“Item”的那些项目。

如果您需要更多信息,请告诉我!

谢谢!

4

3 回答 3

1

如果我理解正确,正在搜索的对象(我们称之为target)在以下情况下是匹配的:

  • 两者searchObjtarget在同一级别共享至少一个属性名称

  • ' 属性的值target等于或包含searchObj' 属性 的值

下面的代码(包括您的编辑)应该可以满足您的需求。我会让你填写任何边缘情况(检查hasOwnProperty,不同类型的比较等)。我认为像这样的过滤应该只在必要时发生,比如当用户键入时。用它创建一个 Angular 过滤器可能太昂贵了,因为它在每个摘要周期上运行:

function objectContains(searchObj, target) {
    for (var property in searchObj) {
        var searchVal = searchObj[property];
        var targetVal = target[property];

        if (isObject(searchVal) && isObject(targetVal)) {
            if(objectContains(searchVal, targetVal)){
                return true;
            }
        }

        if (
            !isObject(searchVal) && !isObject(targetVal) && 
            !isUndefinedOrNull(targetVal) && 
            !isUndefinedOrNull(searchVal) &&
            targetVal.toString().indexOf(searchVal.toString()) !== -1
        ) {
            return true;
        }
    }

    return false;
}

function isUndefinedOrNull(x) {
    return typeof x === "undefined" || x === null;
}

function isObject(x) {
    return typeof x === "object";
}

var filtered = list.filter(function(item) {
    return objectContains(searchObj, item);
});
于 2017-05-27T21:47:28.243 回答
0

试试这个方法。使用true过滤器上的属性来准确获取您搜索的内容!

<li data-ng-repeat="[...] | filter: Ctrl.searchObj:true | orderBy: Ctrl.orderBy">
...
</li>
于 2017-05-27T21:53:35.280 回答
0

因此,以 Frank Modica 的代码为基础(谢谢),我提出了一些关于其compare功能的版本,不仅可以查找第一个属性,而且如果不匹配,请继续搜索。这是修改后的代码:

function objectContains(searchObj, target) {
    for (var property in searchObj) {
        var searchVal = searchObj[property];
        var targetVal = target[property];

        if (isObject(searchVal) && isObject(targetVal)) {
            if(objectContains(searchVal, targetVal)){
                return true;
            }
        }

        if (
            !isObject(searchVal) && !isObject(targetVal) && 
            !isUndefinedOrNull(targetVal) && 
            !isUndefinedOrNull(searchVal) &&
            targetVal.toString().indexOf(searchVal.toString()) !== -1
        ) {
            return true;
        }
    }

    return false;
}

如果它匹配,它返回 true,因为它只需要一个匹配就是我们正在寻找的。如果不匹配,它会继续运行。

我们检查第二个条件不是对象,这两个值都不是,因为[object OBJECT]当我们应用它们时它们会转向toString(),所以它true总是返回。这样,如果它是一个对象,它将忽略它(不需要做进一步的检查,因为我们已经在第一个做过if)。

谢谢弗兰克,因为我想不出这个!

现在,它完美运行!

于 2017-05-29T09:13:50.413 回答