在遍历两个数组时无法读取未定义的属性'id':Angular
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在遍历两个数组时无法读取未定义的属性'id':Angular相关的知识,希望对你有一定的参考价值。
我认为我可能缺少一些小东西,或者我没有正确实现我的角度代码。不过,我当前收到的错误是:
TypeError:无法读取未定义的属性'id'
我正在尝试在我的[[newsfeed.component.html(模板)中调用一个函数,该函数调用一个具有id并循环遍历两个数组的函数,这些数组定义在我的[[< [newsfeed.component.ts(组件)(请参见下文)
newsfeed.component.ts:import {
Component,
OnInit,
Input,
OnChanges,
SimpleChanges
} from "@angular/core";
//import { FeedService } from "src/app/core/news-feed";
import { FeedService } from "../../../core/news-feed/_services/feed.service.fake";
import { CustomersService } from "../../../core/e-commerce";
import { MockFeedTable } from "../../../core/news-feed/_server/feed.mock-table";
import moment from "moment";
import { Observable } from "rxjs";
import { SearchPipe } from "../../partials/_pipes/search.pipe";
import { FeedTagsService } from "../../../../../src/app/core/news-feed/_services/feed-tags.service";
import { ActivatedRoute } from "@angular/router";
export interface MOCK_UserData {
id: number;
userName: string;
profileImagePath: string;
}
export interface MOCK_NewsPost {
id: number;
bookmarkCount: number;
commentCount: number;
timeLastUpdated: string;
}
@Component({
selector: "kt-news-feed",
templateUrl: "./news-feed.component.html",
styleUrls: ["./news-feed.component.scss"]
})
export class NewsFeedComponent implements OnInit {
filterQuery: any;
componentDataLoaded: boolean;
constructor(
private feedService: FeedService,
private feedTagsService: FeedTagsService,
private route: ActivatedRoute
) {}
MOCK_UserDataTable: MOCK_UserData[] = [
{
id: 1,
userName: "NUS",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/nus-logo.jpg"
},
{
id: 2,
userName: "POWERLEAGUE Student",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/powerleague-logo.png"
},
{
id: 3,
userName: "NUS",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/nus-logo.jpg"
},
{
id: 4,
userName: "Northumbria University",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/northumbria-uni-logo.png"
},
{
id: 5,
userName: "Northumbria Mens Football",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/team-northumbria-logo.jpg"
},
{
id: 6,
userName: "Northumbria Students Union",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/nsu-logo.jpg"
},
{
id: 7,
userName: "Student Finance England",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/sfe-logo.png"
},
{
id: 8,
userName: "Amazon Prime Student",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/amazon-prime-logo.jpg"
},
{
id: 9,
userName: "Google Scholarships",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/google-logo.png"
},
{
id: 10,
userName: "Northumbria University",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/northumbria-uni-logo.png"
},
{
id: 11,
userName: "Northumbria BSc Accounting And Finance",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/af-logo.png"
},
{
id: 12,
userName: "Northumbria Students Union",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/nsu-logo.jpg"
},
{
id: 13,
userName: "Lost Property",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/lp-logo.png"
},
{
id: 14,
userName: "Northumbria University Campus 24 Hour Security",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/24h-logo.png"
},
{
id: 15,
userName: "Northumbria University Examiners Office",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/eo-logo.png"
},
{
id: 16,
userName: "Enterprise Society",
profileImagePath:
"../../../../assets/media/stuserve-mock-post-users/es-logo.png"
}
];
NEWS_DATA: any;
NEWS_TAG_DATA: any;
currentNewsQuery: any;
ngOnInit() {
this.componentDataLoaded = false;
this.route.data.subscribe(res => {
this.NEWS_DATA = res.newsfeed;
console.log(res.newsfeed);
this.NEWS_TAG_DATA = res.newsfeedtags;
console.log(res.newsfeedtags);
});
}
waitForComponentData() {
console.log("Entered waitForComponentData");
console.log(" componentDataLoaded is currently : ");
console.log(this.componentDataLoaded);
this.componentDataLoaded = true;
console.log(" componentDataLoaded is now : ");
console.log(this.componentDataLoaded);
}
filterNewsPosts() {
return this.feedService.retrieveSearchBarQuery();
}
getUserProfilePictureFromUserId(userId) {
for (var i = 0, len = this.MOCK_UserDataTable.length; i < len; i++) {
if (this.MOCK_UserDataTable[i].id == userId) {
return this.MOCK_UserDataTable[i].profileImagePath;
}
}
}
getUserNameFromUserId(userId) {
for (var i = 0, len = this.MOCK_UserDataTable.length; i < len; i++) {
if (this.MOCK_UserDataTable[i].id == userId) {
return this.MOCK_UserDataTable[i].userName;
}
}
}
getNewsPostElapsedTime(startDate) {
return moment(startDate).fromNow();
}
getFilterTagIdsFromNewsPost(postId: any) {
console.log(
"getFilterTagIdsFromNewsPost : postId from parameter is: " + postId
);
for (var i = 0; i <= this.NEWS_DATA.length; i++) {
if (postId == this.NEWS_DATA[i].id) {
console.log(
"getFilterTagIdsFromNewsPost : returning the following tags: " +
this.NEWS_DATA[i].postTags
);
return this.NEWS_DATA[i].postTags;
}
}
}
getFilterTagsFromNewsPost(postId: any) {
var tagIdArray = this.getFilterTagIdsFromNewsPost(postId);
let newsDataArray = this.NEWS_DATA;
let newsTagDataArray = this.NEWS_TAG_DATA;
var resultTagArray = [];
console.log("tagIdArray for Post with id of " + postId + " is :");
console.log(tagIdArray);
console.log("Looping through first loop...");
for (var i = 0; i <= tagIdArray.length; i++) {
console.log("Looping through second loop...");
for (var j = 0; j <= newsTagDataArray.length; j++) {
if (tagIdArray[i] == newsTagDataArray[j].id) {
resultTagArray.push(newsTagDataArray[j]);
}
}
}
console.log("Final Array for this post is: ");
console.log(resultTagArray);
return resultTagArray;
}
}
newsfeed.component.html:
<!-- Left col -->
<!-- <div class="row" *ngIf="!componentDataLoaded">
<div class="col-sm">
<div
class="kt-spinner kt-spinner--v2 kt-spinner--lg kt-spinner--info"
></div>
</div>
</div> -->
<div class="row">
<div class="col-lg-6">
<ng-container
*ngFor="
let newsData of NEWS_DATA | NewsStringFilter: filterNewsPosts()
"
>
<!-- CARD START -->
<div *ngIf="!newsData.oddNewsPostInDatabase" class="kt-portlet">
<div class="kt-portlet__head" style="margin-top: 15px;">
<div class="kt-portlet__head-label">
<span class="kt-portlet__head-icon">
<a
href="#"
class="kt-media kt-media--lg kt-media--circle"
>
<img
src="{{
getUserProfilePictureFromUserId(
newsData._userId
)
}}"
alt="profile-image"
/>
</a>
</span>
<h3 class="kt-portlet__head-title">
{{ getUserNameFromUserId(newsData._userId) }}
</h3>
</div>
<div class="kt-portlet__head-toolbar">
{{ getNewsPostElapsedTime(newsData._createdDate) }}
</div>
</div>
<div class="kt-portlet__body">
<h4>
{{ newsData.postHeader }}
</h4>
{{ newsData.postBody }}
</div>
<div class="kt-portlet__foot">
<div class="kt-portlet__head-toolbar">
<div class="kt-portlet__head-actions">
<ng-container
*ngFor="
let newsTag of getFilterTagsFromNewsPost(
newsData.id
)
"
>
<td class="card-tag-container">
<span
class="kt-badge kt-badge--inline cat-tab"
[style.background-color]="
newsTag.tagColour
"
style="color: #ffffff"
>{{ newsTag.tagTitle }}</span
>
</td>
</ng-container>
<a
href="#"
class="btn btn-outline-brand btn-sm btn-icon btn-icon-md"
>
<i
class="flaticon2-tag
"
></i>
</a>
<a
href="#"
class="btn btn-outline-brand btn-sm btn-icon btn-icon-md"
>
<i class="flaticon-comment"></i>
</a>
</div>
</div>
</div>
</div>
<!-- CARD END -->
<!-- CARD END -->
</ng-container>
</div>
<!-- Right col -->
<div class="col-lg-6">
<ng-container
*ngFor="
let newsData of NEWS_DATA | NewsStringFilter: filterNewsPosts()
"
>
<!-- CARD START -->
<div *ngIf="newsData.oddNewsPostInDatabase" class="kt-portlet">
<div class="kt-portlet__head" style="margin-top: 15px;">
<div class="kt-portlet__head-label">
<span class="kt-portlet__head-icon">
<a
href="#"
class="kt-media kt-media--lg kt-media--circle"
>
<img
src="{{
getUserProfilePictureFromUserId(
newsData._userId
)
}}"
alt="profile-image"
/>
</a>
</span>
<h3 class="kt-portlet__head-title">
{{ getUserNameFromUserId(newsData._userId) }}
</h3>
</div>
<div class="kt-portlet__head-toolbar">
{{ getNewsPostElapsedTime(newsData._createdDate) }}
</div>
</div>
<div class="kt-portlet__body">
<h4>
{{ newsData.postHeader }}
</h4>
{{ newsData.postBody }}
</div>
<div class="kt-portlet__foot">
<div class="kt-portlet__head-toolbar card-footer-toolbar">
<div class="kt-portlet__head-actions">
<ng-container
*ngFor="
let newsTag of getFilterTagsFromNewsPost(
newsData.id
)
"
>
<td class="card-tag-container">
<span
class="kt-badge kt-badge--inline cat-tab"
[style.background-color]="
newsTag.tagColour
"
style="color: #ffffff"
>{{ newsTag.tagTitle }}</span
>
</td>
</ng-container>
<a
href="#"
class="btn btn-outline-brand btn-sm btn-icon btn-icon-md"
>
<i
class="flaticon2-tag
"
></i>
</a>
<a
href="#"
class="btn btn-outline-brand btn-sm btn-icon btn-icon-md"
>
<i class="flaticon-comment"></i>
</a>
</div>
</div>
</div>
</div>
</ng-container>
<!-- CARD END -->
</div>
</div>
最初,我认为该视图执行了相关功能:(getFilterTagsFromNewsPost(newsData.id))在通过可观察的填充变量(
NEWS_DATA和NEWS_TAG_DATA)将数据加载到组件中并因此抛出“ undefined”之前。
因此,我尝试将分解器实现,希望这是问题所在,事实证明我仍然做错了。解析程序和服务的代码如下:feed.service.fake.ts
// Angular import { Injectable } from "@angular/core"; import { HttpClient } from "@angular/common/http"; // RxJS import { Observable, forkJoin, of } from "rxjs"; import { mergeMap, delay } from "rxjs/operators"; // Lodash import { each } from "lodash"; // CRUD import { HttpUtilsService, QueryParamsModel, QueryResultsModel } from "../../_base/crud"; // Models import { NewsPostModel } from "../_models/news-post.model"; const API_NEWS_POST_URL = "api/newsfeed"; // Fake REST API (Mock) // This code emulates server calls @Injectable() export class FeedService { NEWS_FEED_ITEMS_STORAGE: any; public currentSearchBarQuery: any; constructor( private http: HttpClient, private httpUtils: HttpUtilsService ) {} // CREATE => POST: add a new newsPost to the server createNewsPost(newsPost: NewsPostModel): Observable<NewsPostModel> { // Note: Add headers if needed (tokens/bearer) const httpHeaders = this.httpUtils.getHTTPHeaders(); return this.http.post<NewsPostModel>(API_NEWS_POST_URL, newsPost, { headers: httpHeaders }); } // READ getAllNewsPosts(): Observable<NewsPostModel[]> { return this.http.get<NewsPostModel[]>(API_NEWS_POST_URL); } getNewsPostById(newsPostId: number): Observable<NewsPostModel> { return this.http.get<NewsPostModel>( API_NEWS_POST_URL + `/${newsPostId}` ); } // Method from server should return QueryResultsModel(items: any[], totalsCount: number) // items => filtered/sorted result findNewsPosts( queryParams: QueryParamsModel ): Observable<QueryResultsModel> { // This code imitates server calls const url = API_NEWS_POST_URL; return this.http.get<NewsPostModel[]>(API_NEWS_POST_URL).pipe( mergeMap(res => { const result = this.httpUtils.baseFilter(res, queryParams, [ "status", "type" ]); return of(result); }) ); } // UPDATE => PUT: update the newsPost on the server updateNewsPost(newsPost: NewsPostModel): Observable<any> { const httpHeader = this.httpUtils.getHTTPHeaders(); return this.http.put(API_NEWS_POST_URL, newsPost, { headers: httpHeader }); } // UPDATE Status updateStatusForNewsPost( newsPosts: NewsPostModel[], status: number ): Observable<any> { const tasks$ = []; each(newsPosts, element => { const _newsPost = Object.assign({}, element); _newsPost.status = status; tasks$.push(this.updateNewsPost(_newsPost)); }); return forkJoin(tasks$); } // DELETE => delete the newsPost from the server deleteNewsPost(newsPostId: number): Observable<any> { const url = `${API_NEWS_POST_URL}/${newsPostId}`; return this.http.delete<NewsPostModel>(url); } deleteNewsPosts(ids: number[] = []): Observable<any> { const tasks$ = []; const length = ids.length; // tslint:disable-next-line:prefer-const for (let i = 0; i < length; i++) { tasks$.push(this.deleteNewsPost(ids[i])); } return forkJoin(tasks$); } fetchSearchBarQuery(value: any): any { this.currentSearchBarQuery = value; } retrieveSearchBarQuery(): any { return this.currentSearchBarQuery; } }
feed-tags.service.ts
// Angular
import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
// RxJS
import { Observable } from "rxjs";
// CRUD
import {
HttpUtilsService,
QueryParamsModel,
QueryResultsModel
} from "../../_base/crud";
// Models
import { NewsPostTagModel } from "../_models/news-post-tag.model";
const API_NEWS_POST_TAG_URL = "api/newsfeedtags";
@Injectable()
export class FeedTagsService {
NEWS_TAG_STORAGE: any;
SELECTED_NEWS_TAG_STORAGE: any;
constructor(
private http: HttpClient,
private httpUtils: HttpUtilsService
) {}
// CREATE => POST: add a new NewsPost to the server
createNewsPostTag(
newsPostTag: NewsPostTagModel
): Observable<NewsPostTagModel> {
// Note: Add headers if needed (tokens/bearer)
const httpHeaders = this.httpUtils.getHTTPHeaders();
return this.http.post<NewsPostTagModel>(
API_NEWS_POST_TAG_URL,
newsPostTag,
{
headers: httpHeaders
}
);
}
// READ
getAllNewsPostsTags(): Observable<NewsPostTagModel[]> {
return this.http.get<NewsPostTagModel[]>(API_NEWS_POST_TAG_URL);
}
getNewsPostTagsById(newsPostTagId: number): Observable<NewsPostTagModel> {
return this.http.get<NewsPostTagModel>(
API_NEWS_POST_TAG_URL + `/${newsPostTagId}`
);
}
// Method from server should return QueryResultsModel(items: any[], totalsCount: number)
// items => filtered/sorted result
// Server should return filtered/sorted result
findNewsPostsTags(
queryParams: QueryParamsModel
): Observable<QueryResultsModel> {
// Note: Add headers if needed (tokens/bearer)
const httpHeaders = this.httpUtils.getHTTPHeaders();
const httpParams = this.httpUtils.getFindHTTPParams(queryParams);
const url = API_NEWS_POST_TAG_URL + "/find";
return this.http.get<QueryResultsModel>(url, {
headers: httpHeaders,
params: httpParams
});
}
// UPDATE => PUT: update the NewsPost on the server
updateNewsPostTag(newsPostTag: NewsPostTagModel): Observable<any> {
const httpHeader = this.httpUtils.getHTTPHeaders();
return this.http.put(API_NEWS_POST_TAG_URL, newsPostTag, {
headers: httpHeader
});
}
// UPDATE Status
updateStatusForNewsPostTagModel(
newsPostsTags: NewsPostTagModel[],
status: number
): Observable<any> {
const httpHeaders = this.httpUtils.getHTTPHeaders();
const body = {
newsPostsForUpdate: newsPostsTags,
newStatus: status
};
const url = API_NEWS_POST_TAG_URL + "/updateStatus";
return this.http.put(url, body, { headers: httpHeaders });
}
// DELETE => delete the newsPost from the server
deleteNewsPostTag(newsPostTagId: number): Observable<NewsPostTagModel> {
const url = `${API_NEWS_POST_TAG_URL}/${newsPostTagId}`;
return this.http.delete<NewsPostTagModel>(url);
}
deleteNewsPostsTags(ids: number[] = []): Observable<any> {
const url = API_NEWS_POST_TAG_URL + "/deleteNewsPostsTags";
const httpHeaders = this.httpUtils.getHTTPHeaders();
const body = { newsPostIdsForDelete: ids };
return this.http.put<QueryResultsModel>(url, body, {
headers: httpHeaders
});
}
}
news-feed-tags.resolve.ts:News Feed Tags resolve Image
news-feed.resolve.ts:News feed resolve image这里是带有各种日志和错误的控制台:Logs and Errors Image
如您所见,数据似乎正在通过日志中输出的各个值(特别是id值)传递,但是似乎在数组中的隐藏元素上引发了错误?目前不知道。
i <= tagIdArray.length
→i < tagIdArray.length
j <= newsTagDataArray.length
→j < newsTagDataArray.length
注意以下内容如何打印未定义,因为x[x.length]
始终是未定义的。
x = [10, 11, 12]; for (var i = 0; i <= x.length; i++) { console.log(x[i]); }
以上是关于在遍历两个数组时无法读取未定义的属性'id':Angular的主要内容,如果未能解决你的问题,请参考以下文章
遍历对象数组-TypeError:无法读取未定义的属性“名称”
Discord.js TypeError:无法读取未定义的属性'id'-channel.id
无法读取 nativescript angular2 中未定义的属性全局数组