2017-05-08 4 views
3

Ich habe eine FormGroup mit ValueChanges-Ereignis, das aus dem Speicher nicht freigegeben wird, wenn der Benutzer von der Route der Komponente zu einer anderen Komponente wechselt und dann zu der Komponente zurückkehrt.Angular 2 - FormGroup ValueChanges Abbestellen

Dies bedeutet, dass die Methode onFormChange fünf Mal ausgelöst wird, wenn der Benutzer fünfmal von der Komponente und dann zurück zur Komponente navigiert, wobei nur eine dieser Aufrufe für die aktuelle Komponente gilt.

Ich dachte, dass das Problem war, dass ich das valueChanges-Ereignis im NgDestroy-Ereignis abmelden musste, aber es gibt keine Methode zum Abmelden für das valueChanges-Ereignis.

Ich bin sicher, ich muss Speicher abmelden oder freigeben für etwas, aber ich bin mir nicht sicher was.

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); 
    } 
} 

Antwort

2

Der subscribe() Aufruf gibt ein Subscription und das ist, was Sie sich abmelden verwenden:

class JobToolbarComponent 

    private subscr:Subscription; 

    ngOnInit() { 
    ... 
    this.subscr = this.form.valueChanges ... 
    ... 
    } 

    ngOnDestroy() { 
    this.subscr.unsubscribe(); 
    } 
} 
+0

Dank Das hat für mich funktioniert –

0

Ich habe diese folgende Funktion erstellt

export function AutoUnsubscribe(exclude = []) { 

    return function (constructor) { 

     const original = constructor.prototype.ngOnDestroy; 

     constructor.prototype.ngOnDestroy = function() { 
      for (let prop in this) { 
       const property = this[prop]; 
       if (!exclude.includes(prop)) { 
        if (property && (typeof property.unsubscribe === "function")) { 
         property.unsubscribe(); 
        } 
       } 
      } 
      original && typeof original === 'function' && original.apply(this, arguments); 
     }; 
    } 

} 

, die tatsächlich können Sie die automatische Abmelde verwenden Alle Beobachter müssen jedoch in öffentlichen Eigenschaften gespeichert werden, damit diese Funktion sie abfangen und den Abmeldeservice aufrufen kann. Wie Sie es verwenden, wird im Folgenden aufgeführt sind: -

@AutoUnsubscribe() 
@Component({ 
    selector: 'account-login', 
    templateUrl: './login.component.html', 
    styleUrls: ['./login.component.scss'] 
}) 
export class LoginComponent implements OnInit { 


    public submitWatcher: Subscription; 

    submit() { 
     this.submitWatcher = this.authService.login(this.loginForm.getRawValue()) 
      .subscribe(res => { 
       if (this.returnUrl) { 
        this.router.navigate([this.returnUrl]); 
       } 
       else { 
        this.router.navigate(['/special']); 
       } 
      }, (error) => { 
       alert(JSON.stringify(error.data)); 
      }); 
    } 

} 

Weitere Informationen darüber, wie Dekorateur verwenden Sie bitte diesen Blog lesen, das ist, wo ich von der Idee genommen haben, und es ist ziemlich cool

Blog

Verwandte Themen