1

I have 2 component a Moment(post/thread) and a Comment, each moment can have multiple comments.

Inside the moment-details.component i insert a moment-comment.component. The comment component shows all comments associate with the moment.

moments-detail.component.html

<div id="moment">

...

            <app-moment-comment [moment]="moment" [auth]="auth" [comment]="comment" class="comment" *ngFor="let comment of moment?.comments; let i=index">
            </app-moment-comment>


        </div>
    </div>
</div>

moment-detail.component.ts

@Component({
    selector: 'app-moment-detail',
    templateUrl: './moment-detail.component.html',
    styleUrls: ['./moment-detail.component.scss']
})
export class MomentDetailComponent implements OnInit {

    moment: Moment;

    constructor(private router: Router,
        private route: ActivatedRoute,
        private momentService: MomentService,
        private authService: AuthService,
        private commentService: CommentService) { }

    ngOnInit() {

        this.route.params.switchMap((params) => {
            let moment_id = params['id'];
            return this.momentService.get(moment_id);
        }).subscribe((res) => {
            console.log(res);
            this.moment = res;
            this.user = res.author;
        });

        this.authService.getAuthenticatedUser().subscribe((res) => {
            this.auth = res;
        });

    }
}

The moment-comment loops through all the comments and creates a new instance of the moment-comment component.

Now within the moment-comment.component.ts a user can trigger a deletion of their comment.

@Component({
    selector: 'app-moment-comment',
    templateUrl: './moment-comment.component.html',
    styleUrls: ['./moment-comment.component.scss']
})
export class MomentCommentComponent implements OnInit {

    @Input() comment: Comment;
    @Input() auth: any;
    @Input() moment: any;
    showReply: any;
    reply: any;
    showReplies: boolean;
    inEdit = false;
    editComment: any;

    constructor(private commentService: CommentService) { }

...
    delete() {

        this.commentService.delete(this.moment._id, this.comment._id).subscribe((res) => {
            console.log(res);
        }, (err) => {
            console.log(err);
        });

    }
...
}

Sure enough when delete() function is triggered by the user the backend updates my database to show the comment is removed from the moment.

My question is, how can i reflect this change in frontend i.e the parent (moment-details) view?

Stefan Falk
  • 23,898
  • 50
  • 191
  • 378
Kay
  • 17,906
  • 63
  • 162
  • 270
  • update the object so that `ui` gets updated – Aravind Dec 06 '17 at 11:51
  • @Aravind ye i guess something like that, but from within the moment-comment.component, i don't have access to the entire ```moment?.comments``` as you can see in moment.component in the ngFor. I pass in 1 comment each time. – Kay Dec 06 '17 at 11:53
  • can you reproduce the error in a `plunker` or a `stackblitz` so I can help you fix it – Aravind Dec 06 '17 at 11:55
  • How are you getting the moment?.comments?? – Vinod Bhavnani Dec 06 '17 at 12:03
  • Can you post the moment.detail component ts as well? – Vinod Bhavnani Dec 06 '17 at 12:04
  • @VinodBhavnani Im getting moments from a service. I updated my original question. – Kay Dec 06 '17 at 12:34
  • @Aravind There is no error, too large to reproduce in stackblitz atm. just a question about how do i reflect the change in the parent view – Kay Dec 06 '17 at 12:35
  • @KHAN you can use any of my plunkers. I have implemented the service [**here**](https://stackoverflow.com/questions/42655795/parsing-json-into-a-angular-2-object/42656722#42656722) and parent-child can be seen [**here**](https://stackoverflow.com/questions/40790938/angular-2-header-component-title-change-dynamically-according-to-the-state/42735520#42735520) – Aravind Dec 06 '17 at 12:45
  • @Aravind Dhyey, has provided a working solution for me. Did you have something else in mind? – Kay Dec 06 '17 at 13:06

1 Answers1

3

You need to emit an event from comment component to it's parent i.e detail component and remove the comment from array in detail component like this:

moments-detail.component.html

<div id="moment">

...
        <app-moment-comment (onDelete)="removeComment(i)" [index]="i" 
            [moment]="moment" [auth]="auth" [comment]="comment" class="comment" 
            *ngFor="let comment of moment?.comments; let i=index">
        </app-moment-comment>

        </div>
    </div>
</div>

moments-detail.component.ts

removeComment(index: number) {
    this.moment.comments.splice(index, 1);
}

moment-comment.component.ts

...
@Output() public onDelete: EventEmitter<any> = new EventEmitter();
@Input() comment: Comment;
...

delete() {
    this.commentService.delete(this.moment._id, this.comment._id).subscribe((res) => {
        console.log(res);
        this.onDelete.emit();
    }, (err) => {
        console.log(err);
    });

}
Stefan Falk
  • 23,898
  • 50
  • 191
  • 378
Dhyey
  • 4,275
  • 3
  • 26
  • 33
  • Oh, EventEmitters now i see what there purpose is for. Im having a small problem implementing this and thats when i call the this.onDelete() it says "Cannot invoke an expression whos type lacks a call signature. Type EventEmitter has no compatible call signature" – Kay Dec 06 '17 at 13:04
  • Ahh its this.onDelete.emit() – Kay Dec 06 '17 at 13:06
  • What is your take on the answer here - https://stackoverflow.com/questions/36076700/what-is-the-proper-use-of-an-eventemitter Is this a valid use case for event emitter, as we are not using it in a service? – Kay Dec 06 '17 at 13:09
  • If he is using a service, he doesnt need to emit it from the child component – Vinod Bhavnani Dec 06 '17 at 13:10
  • @KHAN sorry for forgetting `.emit()`, i didn't actually test the code. Yes I think our's is a valid use case as we are doing child to parent component communication. – Dhyey Dec 06 '17 at 14:00