将新数据添加到Firebase后,如何从组件中的Firebase中刷新数据?

时间:2019-05-01 17:07:31

标签: javascript angular firebase google-cloud-firestore

我有ReviewComponent。在此组件中,我显示所有评论,并可以撰写新评论。但是,当我添加新评论时,仅当我单击组件中的链接(“写评论”或“阅读所有评论”)时,所有评论才会刷新。添加新评论后如何刷新所有评论?

review.component.ts

import { Component, OnInit, ChangeDetectionStrategy, Input } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { ItemService } from '../../services/item.service';

@Component({
    changeDetection: ChangeDetectionStrategy.OnPush,
    selector: 'app-review',
    templateUrl: './review.component.html',
    styleUrls: [ './review.component.css' ]
})
export class ReviewComponent implements OnInit {
    @Input() itemId: string;
    stars = [];
    reviewId: string;
    reviews;
    commentBox: boolean = false;
    reviewsBox: boolean = false;
    grades = 0;

    commentForm = this.fb.group({
        comment: [ '' ],
        assessment: [ '1' ]
    });

    constructor(private fb: FormBuilder, private _itemService: ItemService) {}

    ngOnInit() {
        this.getReviews();
    }

    getReviews() {
        this._itemService.getReviews(this.itemId).subscribe((data) => {
            this.reviews = data.map((review) => {
                return {
                    id: review.payload.doc.id,
                    ...review.payload.doc.data()
                };
            });
            this.reviewId = this.reviews.length + '';
            let avgAssess = 0;
            this.reviews.forEach((review) => {
                avgAssess += parseInt(review.assessment);
            });
            this.grades = Math.floor(avgAssess / this.reviews.length);
            console.log(this.grades);
            this.stars = [];
            for (let i = 0; i < this.grades; i++) {
                this.stars.push('grade');
            }
            for (let i = this.grades; i < 5; i++) {
                this.stars.push('star_border');
            }

        });
    }

    showCommentBox() {
        this.commentBox = !this.commentBox;
    }

    showReviewsBox() {
        this.reviewsBox = !this.reviewsBox;
    }

    sendComment() {
        let review = {
            comment: this.commentForm.get('comment').value,
            assessment: this.commentForm.get('assessment').value
        };
        this._itemService.addReview(this.itemId, this.reviewId, review);
        this.showCommentBox();
        this.commentForm.patchValue({
            comment: [ '' ],
            assessment: [ '1' ]
        });
    }

    validPaymentInput(event) {
        var char = String.fromCharCode(event.which);
        if (!/[1-5]/.test(char)) {
            event.preventDefault();
        }
    }
}

item.service.ts

import { Injectable } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';

@Injectable({
    providedIn: 'root'
})
export class ItemService {
    constructor(private _firestore: AngularFirestore) {}

    addReview(key: string, reviewId, review) {
        this._firestore.collection('items').doc(key).collection('reviews').doc(reviewId).set(review);
    }

    getReviews(key: string) {
        return this._firestore.collection('items').doc(key).collection('reviews').snapshotChanges();
    }
}

review.component.html

<div class="container">
    <div>
        <div  class="stars" >
                <mat-icon *ngFor="let star of stars">{{star}}</mat-icon>
                <div>({{reviews.length}})</div>
        </div>
        <div class="reviews" (click)="showReviewsBox()">
                <span>Read all {{reviews.length}} Reviews</span>
        </div>
        <div  class="write" (click)="showCommentBox()">
                <span>Write a review</span>
        </div>
    </div>
    <div class="comment-box" *ngIf="commentBox" [formGroup]="commentForm">
        <div [ngClass]="{'has-error' : commentForm.get('comment').errors && (commentForm.get('comment').touched || commentForm.get('comment').dirty)}">
            <label> Enter a comment</label>
            <textarea formControlName="comment" required></textarea>
            <div class="error-msg" 
                        *ngIf="commentForm.get('comment').errors && (commentForm.get('comment').touched || commentForm.get('comment').dirty)">
                    <span *ngIf="commentForm.get('comment').errors.required">
                        Comment field is required
                    </span>

                </div>
        </div>
        <div [ngClass]="{'has-error' : commentForm.get('assessment').errors && (commentForm.get('assessment').touched || commentForm.get('assessment').dirty)}">

                <label for="">Evaluate from 1 to 5</label>
                <input type="text" (keypress)="validPaymentInput($event)" formControlName="assessment" max="5" maxlength="1" required>
                <app-button btnText="Submit" [disabled]="!commentForm.valid" (click)="sendComment()"></app-button>
            </div>
    </div>
    <div class="reviews-box" *ngIf="reviewsBox && reviews.length > 0">
        <div class="review" *ngFor="let review of reviews">{{ review.comment }}</div>
    </div>


</div>

1 个答案:

答案 0 :(得分:0)

getReviews()方法内调用sendComment()方法。请参考下面的代码段:

sendComment() {
    let review = {
        comment: this.commentForm.get('comment').value,
        assessment: this.commentForm.get('assessment').value
    };
    this._itemService.addReview(this.itemId, this.reviewId, review);
    this.getReviews();
    this.showCommentBox();
    this.commentForm.patchValue({
        comment: [ '' ],
        assessment: [ '1' ]
    });
}

更新:

已经注意到更改检测策略是onPush,这意味着您已经确保所有对象都是不可变的。请将方法getReviews()更改为如下所示:

getReviews() {
    this._itemService.getReviews(this.itemId).subscribe((data) => {
        this.reviews = data.map((review) => {
            return {
                id: review.payload.doc.id,
                ...review.payload.doc.data()
            };
        });
        this.reviewId = this.reviews.length + '';
        let avgAssess = 0;
        this.reviews.forEach((review) => {
            avgAssess += parseInt(review.assessment);
        });
        this.grades = Math.floor(avgAssess / this.reviews.length);
        console.log(this.grades);
        this.stars = [];
        const _stars:any=[];
        for (let i = 0; i < this.grades; i++) {
            _stars.push('grade');
        }
        for (let i = this.grades; i < 5; i++) {
            _stars.push('star_border');
        }
        // to ensure that your object is immutable. Do not change the object content once it is assigned
        this.stars=_stars;
    });
}

更新2:

看起来对象是不可变的,这导致更改检测不起作用。请从您的组件中删除以下行:

changeDetection: ChangeDetectionStrategy.OnPush,