I have a FormGroup with ValueChanges event that is not being released from memory when the user moves from component's route to another component and then they return to the component.
What this means is that if the user navigates away from component and then back to the component 5 times, the onFormChange method fires 5 times, but only 1 of those calls is for the current component.
I figured that the problem was that I needed to unsubscribe from the the valueChanges event in the NgDestroy event, but there is no unsubscribe method available on the valueChanges event.
I am sure I have to unsubscribe or release memory for something, but I'm not sure what.
import * as _ from 'lodash';
import {Observable} from 'rxjs/Rx';
import {Component, Input, Output, EventEmitter, OnInit, OnDestroy} from '@angular/core';
import {FormGroup} from '@angular/forms';
import {formConfig} from './toolbar.form-config';
import {JobToolbarVm} from '../view-model/job-toolbar.vm';
import {BroadcastService} from '../../../services/broadcast/broadcast.service';
@Component({
selector: 'wk-job-toolbar',
template: require('./toolbar.html'),
})
export class JobToolbarComponent implements OnInit, OnDestroy {
protected form: FormGroup;
@Input()
toolbar: JobToolbarVm;
@Output()
toolbarChanged = new EventEmitter<JobToolbarVm>();
@Output()
refresh = new EventEmitter<string>();
constructor(private broadcast: BroadcastService) {
}
ngOnInit() {
this.form = formConfig;
this.form.setValue(this.toolbar, {onlySelf: true});
// This ALWAYS RUNS when the form loads, ie. on the job route
console.log('FORM VALUE');
console.log(JSON.stringify(this.form.value, null, 2));
this.form.valueChanges
.debounceTime(2000)
.subscribe(
this.onFormChange.bind(this)
);
}
ngOnDestroy() {
//this.form.valueChanges.unsubscribe();
//this.onChanges.unsubscribe();
//this.toolbarChanged.unsubscribe();
//this.form = null;
}
onFormChange(data: any) {
// This runs whenever I go to a different route and then come back to this route
// There is also a memory leak, because this method fires multiple times based on how
// often I navigate away and come back to this route.
// e.g. Navigate away and then back 5 times, then I see this log statement 5 times
console.log('FORM VALUE2 - THIS KEEPS FIRING FOR EACH INSTANCE OF MY COMPOMENT');
console.log(JSON.stringify(this.form.value, null, 2));
JobToolbarVm.fromJsonIntoInstance(data, this.toolbar);
this.onChanges('data-changed');
}
onChanges($event: any) {
console.log('onChanges: ' + $event);
// console.log(this.toolbar);
// Send the toolbar object back out to the parent
this.toolbarChanged.emit(this.toolbar);
// Broadcast an event that will be listened to by the list component so that it knows when to refresh the list
this.broadcast.broadcast('job-admin-toolbar-changed', this.toolbar);
}
}
The
subscribe()
call returns aSubscription
and this is what you use to unsubscribe:I have created this following function
which actually you can use to auto unsubscribe all the watchers but you have to store them in public properties so that this function can intercept it and invoke unsubscribe on that. How you use it is mentioned below:-
For more info on how to use decorator please read this blog that's where I have taken the idea from and it is pretty cool
Blog