Невозможно прочитать свойство 'id' из undefined при циклическом просмотре двух массивов: Angular - PullRequest
0 голосов
/ 25 января 2020

Я думаю, что я мог упустить что-то маленькое или неправильно реализовал свой код 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), но, похоже, выдает ошибку скрытого элемента в массиве? На данный момент понятия не имею.

1 Ответ

0 голосов
/ 25 января 2020
        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]);
                }
            }
        }

Вышеприведенный код выглядит неправильно и требует следующих изменений

i <= tagIdArray.lengthi < tagIdArray.length
j <= newsTagDataArray.lengthj < newsTagDataArray.length

Обратите внимание на то, как печатается следующее undefined, потому что x[x.length] всегда неопределен.

x = [10, 11, 12];
for (var i = 0; i <= x.length; i++) {
    console.log(x[i]);
}
...