AngularJS - 按任何属性过滤

AngularJS - Filter by any of the properties

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

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

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

问题

但是,如果我使用 'Item B' 的 AngularJS 过滤器进行搜索,它仍然会出现,因为内部 属性 有这个字符串。

我试过的

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

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

然后,在我的 DOM:

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

但是,这适用于条件 AND,因此仅当 nameuser 都具有 val.

时才会显示

我需要的

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

所以,在这个例子中,如果我写 'Item A' 或 'User C'(或者只是 'A' 或只是 'C' 等等),这个项目应该出现,但是如果我写 'B' 就不会,因为 nameuser 的 none 有这封信。

我需要它获取参考对象,在本例中为 Ctrl.searchObj,并检查对象的任何给定属性是否包含 val 到过滤对象的相同结构中.

那,当然,应该工作到对象的更深层次,所以我可以定义 searchObj 如下,如果过滤后的对象内部有那个结构,仍然能够得到:

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

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

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

谢谢!

如果我理解正确,正在搜索的对象(我们将其称为 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);
});

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

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

因此,以 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;
}

万一它匹配,它 returns 正确,因为它只需要一个匹配项就是我们正在寻找的。如果不匹配,则继续。

我们检查第二个条件是否不是对象,因为当我们应用 toString() 时它们会变成 [object OBJECT],所以它 returns true总是。这样,如果它是一个对象,它将忽略它(不需要做进一步的检查,因为我们已经在第一个 if 中完成了)。

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

现在,它完美运行了!