I have read that every component should unsubscribe to all subscriptions at the end in the
ngOnDestroy()
for instance. I have the following blog component:
import { Component, OnInit } from '@angular/core';
import { ISubscription } from "rxjs/Subscription";
import { CarouselConfig } from 'ngx-bootstrap/carousel';
import { BlogPost } from '../shared/blogPost';
import { BlogPostFactory } from '../shared/blogPost-factory';
import { DataService } from '../data.service';
@Component({
selector: 'ca-blog',
templateUrl: './blog.component.html',
styleUrls: ['./blog.component.css'],
providers: [{provide: CarouselConfig, useValue: {interval: 1500, noPause: true}}]
})
export class BlogComponent implements OnInit {
private blogPosts: BlogPost[] = [];
private heartsUp: string[] = [];
private likesUp: string[] = [];
private heartSub: ISubscription;
private likeSub: ISubscription;
constructor(private dataService: DataService) {
window.onscroll = () => {
let windowHeight = "innerHeight" in window ? window.innerHeight : document.documentElement.offsetHeight;
let body = document.body;
let html = document.documentElement;
let docHeight = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
let windowBottom = windowHeight + window.pageYOffset;
if(windowBottom >= docHeight) {
let urlSearchParams = { last: this.blogPosts.length };
this.dataService.getBlogPosts(urlSearchParams).subscribe( result => {
for(let i=0; i<result.length; i++){
this.blogPosts.push(BlogPostFactory.fromObject(result[i]));
}
});
}
};
}
ngOnInit() {
this.dataService.getBlogPosts().subscribe( result => {
for(let i=0; i<result.length; i++){
this.blogPosts.push(BlogPostFactory.fromObject(result[i]));
}
});
}
incrementHearts(index) : void {
let idIndex : number = this.heartsUp.indexOf(this.blogPosts[index].id);
if(idIndex != -1){
this.blogPosts[index].hearts--;
this.heartsUp.splice(idIndex, 1);
} else {
this.blogPosts[index].hearts++;
this.heartsUp.push(this.blogPosts[index].id);
}
this.heartSub = this.dataService.editBlogPost(this.blogPosts[index].id, { hearts: this.blogPosts[index].hearts }).subscribe();
}
incrementLikes(index) : void {
let idIndex : number = this.likesUp.indexOf(this.blogPosts[index].id);
if(idIndex != -1){
this.blogPosts[index].likes--;
this.likesUp.splice(idIndex, 1);
} else {
this.blogPosts[index].likes++;
this.likesUp.push(this.blogPosts[index].id);
}
this.likeSub = this.dataService.editBlogPost(this.blogPosts[index].id, { likes: this.blogPosts[index].likes }).subscribe();
}
ngOnDestroy() {
// this.likeSub.unsubscribe();
// this.heartSub.unsubscribe();
}
}
But when i uncomment the two lines in the ngOnDestroy()
function then my site crashes. It says that heartSub
and likeSub
is undefined. The appropriate HTML file looks like this:
<div class="container">
<div *ngFor="let blogPost of blogPosts; let i=index">
<div *ngIf="i !== 0">
<hr class="my-5">
</div>
<div class="row">
<div class="col">
<article>
<section>
<header style="" class="mb-4">
<h1 style="display:inline" class="m-0 p-0">{{ blogPost.title }}</h1><small style="opacity:0.5" class="d-block d-sm-inline ml-sm-3">zuletzt bearbeitet am {{ blogPost.lastEdited | date }} von <a href="#" style="color:black"><strong>{{ blogPost.author.username }}</strong></a></small>
<p class="mt-1 mt-sm-auto"><i class="fa fa-tags mr-2"></i><a *ngFor="let hashtag of blogPost.hashtags" href="#" class="badge badge-secondary mr-2">#{{ hashtag }}</a></p>
</header>
<div class="m-0 p-0" [innerHTML]="blogPost.body">
</div>
<div>
<small class="heartUp"><a (click)="incrementHearts(i)" [ngStyle]="{'color':heartsUp.includes(blogPost.id) ? '#E63946' : 'rgba(0,0,0,0.5)'}"><i class="fa fa-heart mr-1"></i>{{ blogPost.hearts }}</a></small>
<small class="likeUp"><a (click)="incrementLikes(i)" [ngStyle]="{'color':likesUp.includes(blogPost.id) ? '#3b5998' : 'rgba(0,0,0,0.5)'}"><i class="fa fa-thumbs-up mr-1"></i>{{ blogPost.likes }}</a></small>
<small class="reply"><a><i class="fa fa-mail-reply mr-1"></i>Reply</a></small>
</div>
<div>
<h2 class="my-3">Kommentare</h2>
<div class="row no-gutters">
<div class="col-auto mr-3">
<img src="https://semantic-ui.com/images/avatar/small/jenny.jpg" class="img-fluid">
</div>
<div class="col">
<h5 style="margin:0;padding:0;display:inline">Joe Henderson</h5><small style="display:inline;margin:0;padding:0;opacity:0.5" class="ml-2"> 1 day ago</small>
<div style="margin:0;padding:0">The hours, minutes and seconds stand as visible reminders that your effort put them all there.
Preserve until your next run, when the watch lets you see how Impermanent your efforts are.</div>
<div>and some other text</div>
<small style="margin:0;padding:0;opacity:0.5;margin-right:10px"><i class="fa fa-heart mr-1"></i>3</small>
<small style="margin:0;padding:0;opacity:0.5;margin-right:10px"><i class="fa fa-thumbs-o-up mr-1"></i>12</small>
<small style="margin:0;padding:0;opacity:0.5"><i class="fa fa-mail-reply mr-1"></i>Reply</small>
</div>
</div>
</div>
</section>
</article>
</div>
</div>
</div>
</div>
It uses the CSS framework Bootstrap, but this shouldnt matter. So my site loads a lot of posts and every post has a like and a heart button which can be pressed up and down by the user. If it's released then i update my post in the database.
I want to unsubscribe from the subscription at the end, but i cant. I don't know whats the problem. :( Nevertheless, i think the up and down voting is really bad written but how could it be done? Im thankful for any help. :)
Best regards, Sven