Я думаю, что я мог упустить что-то маленькое или неправильно реализовал свой код angular. Тем не менее, в настоящее время я получаю ошибку:
TypeError: Невозможно прочитать свойство 'id' из неопределенного
Я пытаюсь вызвать функцию в моем newsfeed.component. html (шаблон), который вызывает функцию, которая принимает идентификатор и перебирает два массива, определенных в верхней части моего 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
) {}
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.resolve.ts : Лента новостей разрешить изображение
Вот консоль с различными журналами и ошибками: Изображение журналов и ошибок
Как видите, данные, похоже, проходят через отдельные значения выводится в журнал (в частности, значение id), но, похоже, выдает ошибку скрытого элемента в массиве? На данный момент понятия не имею.