javascript - AngularJS-如何按对象的属性/属性进行过滤-forEach 不是函数

标签 javascript angularjs foreach filter getattribute

我有一个 AngularJS 应用程序,在其中一个页面上,显示了许多小部件。其中一个小部件显示一个表格,其中包含有关应用程序正在监视的系统的信息。该表当前包含两列:“类型”列,显示该行中显示的信息类型;和“数据”列,显示保存该信息的变量的值。

可以使用单击小部件工具栏上的“设置”按钮时打开的对话框来自定义小部件上显示的信息。该对话框上有“列”和“行”文本输入字段,用于设置要在表中显示的列标题和行。目前,当用户开始在“行”文本输入字段中输入内容时,会显示一个下拉列表,向用户显示可在表中显示的变量,并且这些变量与用户输入的内容相匹配(即,当他们继续输入时)键入时,可用选项列表将变得更加具体)。

当用户在文本输入字段中键入内容时,用于向用户显示此下拉列表的函数是:

$scope.autocompleteVarsFilter = function(query) {
    if(!query && lastVarQryKw) {
        query = lastVarQryKw;
    }
    var result = Object.keys(fxVar.getVars()).filter(function(name) {
        return name.indexOf(query.toLowerCase()) !== -1;
    });

    if(result.length > 0) {
        lastVarQryKw = query;
    }
    return result;
};

我目前正在尝试向该表添加第三列,以显示用户将选择的给定页面的链接。我决定用一个以字符 : 开头的字符串来表示“链接”。 (即,如果用户输入 :index ,这将是指向网站主页的链接)。

一旦用户输入 : ,可用页面的完整列表应显示在“下拉列表”中,并且当用户继续键入时,应根据他们键入的内容(与变量名称一样)过滤此列表

我已更新我的功能如下:

$scope.autocompleteVarsFilter = function(query) {
    if(query.startWith(":") {
        var buttonsQuery = query.substring(1);
        if(!buttonsQuery && lastVarQryKw) {
            buttonsQuery = lastVarQryKw;
        }

        var userPages = pagesPresets; //This is getting the full list of available pages from a service called 'pagesPresets'
        console.log("Value of userPages: ", userPages);

        var page;
        for(page in userPages) {
            console.log("for loop started");
            if(page.key.startWith(buttonsQuery)) {
                console.log("Matching page found: ", page);
            }
        }

        if(result.length > 0) {
            lastVarQryKw = query;
        }
        return result;

    } else {
        if(!query && lastVarQryKw) {
            query = lastVarQryKw;
        }
        var result = Object.keys(fxVar.getVars()).filter(function(name) {
            return name.indexOf(query.toLowerCase()) !== -1;
        });

        if(result.length > 0) {
            lastVarQryKw = query;
        }

        return result;
    }
};

else if 的条款语句正在执行该函数最初执行的操作(即显示可用变量),并且当前仍然按预期工作。但是,在测试此功能时,如果我现在输入 :后跟任何字符串到文本输入字段中,if子句运行,但可用页面未显示在下拉列表中,并且我看到我的 console.log() 在控制台中显示以下输出声明:

Value of userPages:

0: {_id: "...", _rev: 1, _url: "...", key: "pages/auth", {...}, ...}

1: {_id: "...", _rev: 13, _url: "...", key: "pages/userpage2", value: {...}, ...}

2: {_id: "...", _rev:13, _url: "...", key: "pages/", value: "/pages/userpage1", ...}

for loop started

类型错误:无法读取未定义的属性“startsWith”

问题似乎是我无法引用 key userpage 对象的 attribute/属性,将其值与用户在文本框中输入的值相匹配。

鉴于我可以看到 page我正在使用的对象有一个属性 key包含我想要过滤的值,我实际上如何获取这个 key属性要使用它吗?

我尝试更改 for循环到:

var page;
var key;
for(page in userPages) {
    console.log("for loop started");
    key = page.getAttribute("key");
    if(key.startsWith(buttonsQuery)) {
        console.log("Matching page found: ", page);
    }
}

但这只是给出输出:

for loop started

TypeError: page.getAttribute is not a function

大家有什么建议吗?

编辑

我尝试按照@Alex K 在他们的答案中建议的方式进行操作,并更新了 for在我的函数中循环:

var page;
var pageKey;
var key;
var result;

console.log("Iterating using foreach");
for(page in userPages) {
    page = userPages[page];
    if(page.key.startsWith(buttonsQuery)) {
        console.log("Matching page found: ", page.key);
        pageKey = page.key;
        result = pageKey;
    }
};

我还尝试将其更新为:

userPages.forEach(function(page) {
    page = userPages[page];
    if(page.key.startsWith(buttonsQuery)) {
        console.log("Matching page found: ", page.key);
        pageKey = page.key;
        result = pageKey;
    }
});

和:

userPages.forEach(function(page) {
    page = userPages[page];
    if(page.key.startsWith(buttonsQuery)) {
        console.log("Matching page found: ", page.key);
        pageKey = page.key;
        result = pageKey;
    }
});

但是这些都在控制台中给出了相同的输出,即:

Iterating using foreach

ctrl.js:483 Matching page found: pages/userpage2

ctrl.js:483 Matching page found: pages/userpage1

ctrl.js:483 Matching page found: pages/

ctrl.js:483 Matching page found: pages/pagetitle

ctrl.js:483 Matching page found: pages/auth

angular.js:10160 TypeError: a.forEach is not a function
at Object.b.makeObjectArray (ng-tags-input.min.js:1)
at ng-tags-input.min.js:1
at wrappedCallback (angular.js:11735)
at wrappedCallback (angular.js:11735)
at angular.js:11821
at Scope.$eval (angular.js:12864)
at Scope.$digest (angular.js:12676)
at Scope.$apply (angular.js:12968)
at angular.js:14494
at completeOutstandingRequest (angular.js:4413)

非常清楚 if 内部的线条语句正在运行,因为我在控制台中获取了所有这些打印语句,但由于某种原因,它认为 forEach不是一个函数...

有人对如何解决这个问题有任何建议吗?

最佳答案

一个for...in loop迭代对象的可枚举属性名称。然后,您需要使用该属性名称访问该对象以获取值。这是一个例子:

console.log('Using for...in on an object:');

var myObj = {
  'prop1': 'Hello world!',
  'prop2': 12345,
  'some crazy property': null
};

for (var propName in myObj) {

  console.log('propName is ' + propName);

  //Now we can lookup the value using that property name.
  var propValue = myObj[propName];

  console.log('myObj[' + propName + '] is ' + propValue);

}

相比之下,forEach loop直接迭代数组。您的回调函数直接提供值,因此您不需要访问数组来检索它。示例:

console.log('Using forEach on an array:');

var myArray = [
  {key: 'this is object 1!'},
  {key: 'this is object 2!'}
];

myArray.forEach(function (obj) {
  
  console.log('in ForEach loop...');
  
  console.log('obj is ' + JSON.stringify(obj));
  
  //We can directly access the object's properties as needed
  console.log('obj.key is ' + obj.key);
  
});

因此,以下是如何使用 for...in 或使用 forEach 更新代码:

var buttonsQuery = 'pages/userpage2';

var userPages = [{
    _id: "...",
    _rev: 1,
    _url: "...",
    key: "pages/auth"
  },
  {
    _id: "...",
    _rev: 13,
    _url: "...",
    key: "pages/userpage2"
  },
  {
    _id: "...",
    _rev: 13,
    _url: "...",
    key: "pages/",
    value: "/pages/userpage1"
  }
]

console.log('Iterating using for...in');
for (var prop in userPages) {

  console.log('prop is ' + prop);

  //Access the page object using the property name
  var page = userPages[prop];

  console.log('page is ' + JSON.stringify(page));

  if (page.key.startsWith(buttonsQuery)) {
    console.log("Matching page found: ", page);
  }
}


//Better way to iterate if userPages is an array:
console.log('iterating using forEach');
userPages.forEach(function(page) {

  //page is already the object we're interested in.
  //No need to access the array again.
  console.log('page is ' + JSON.stringify(page));

  //Access the object's properties as needed
  if (page.key.startsWith(buttonsQuery)) {
    console.log("Matching page found: ", page);
  }
});

您还可以使用for...of loop迭代,但 IE 不支持。

关于javascript - AngularJS-如何按对象的属性/属性进行过滤-forEach 不是函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47332444/

相关文章:

javascript - 在 pdf.js 中复制 Canvas

javascript - 如果它们的 Prop 不同,如何流动类型组件 Prop 和getDerivedStateFromProps?

asp.net - AngularJS 与 ASP.NET Updatepanel 部分更新

php - 把Array json放到mysql返回Array

r - 在 R 中获取迭代器的索引(与 foreach 并行)

javascript - 没有白色背景的淡入/淡出背景图像

javascript - 如何动态获取所选选项的值并将其存储到变量中?

javascript - 如何使用 window.open() 下载文件

c# - 在 C# 中读取 XML

java - 如何使用流比较列表的元素?