Skip to content

unsubscribe some subscriptions on destroy / first some subscriptions #1549

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 20, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/lib/core/line/line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
QueryList
} from '@angular/core';

import { Subscription } from 'rxjs/Subscription';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove spaces from around imported symbol

/**
* Shared directive to count lines inside a text area, such as a list item.
* Line elements can be extracted with a @ContentChildren(MdLine) query, then
Expand All @@ -16,15 +17,20 @@ export class MdLine {}

/* Helper that takes a query list of lines and sets the correct class on the host */
export class MdLineSetter {
private _changesSubscription: Subscription;

constructor(private _lines: QueryList<MdLine>, private _renderer: Renderer,
private _element: ElementRef) {
this._setLineClass(this._lines.length);

this._lines.changes.subscribe(() => {
this._changesSubscription = this._lines.changes.subscribe(() => {
this._setLineClass(this._lines.length);
});
}

public destroy() {
this._changesSubscription.unsubscribe();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This particular unsubscription isn't necessary because the QueryList will be destroyed at the same time as the component (and the subscription is contained within the component that also contains this LineSetter).


private _setLineClass(count: number): void {
this._resetClasses();
Expand Down
2 changes: 1 addition & 1 deletion src/lib/dialog/dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export class MdDialog {
let dialogRef = <MdDialogRef<T>> new MdDialogRef(overlayRef);

// When the dialog backdrop is clicked, we want to close it.
overlayRef.backdropClick().subscribe(() => dialogRef.close());
overlayRef.backdropClick().first().subscribe(() => dialogRef.close());

// Set the dialogRef to the container so that it can use the ref to close the dialog.
dialogContainer.dialogRef = dialogRef;
Expand Down
9 changes: 7 additions & 2 deletions src/lib/grid-list/grid-tile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
Input,
ContentChildren,
QueryList,
AfterContentInit
AfterContentInit,
OnDestroy
} from '@angular/core';
import { MdLine, MdLineSetter } from '../core';
import {coerceToNumber} from './grid-list-measure';
Expand Down Expand Up @@ -58,7 +59,7 @@ export class MdGridTile {
selector: 'md-grid-tile-header, md-grid-tile-footer',
templateUrl: 'grid-tile-text.html'
})
export class MdGridTileText implements AfterContentInit {
export class MdGridTileText implements AfterContentInit, OnDestroy {
/**
* Helper that watches the number of lines in a text area and sets
* a class on the host element that matches the line count.
Expand All @@ -71,5 +72,9 @@ export class MdGridTileText implements AfterContentInit {
ngAfterContentInit() {
this._lineSetter = new MdLineSetter(this._lines, this._renderer, this._element);
}

ngOnDestroy() {
this._lineSetter.destroy();
}
}

4 changes: 2 additions & 2 deletions src/lib/icon/icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,11 @@ export class MdIcon implements OnChanges, OnInit, AfterViewChecked {
if (changedInputs.indexOf('svgIcon') != -1 || changedInputs.indexOf('svgSrc') != -1) {
if (this.svgIcon) {
const [namespace, iconName] = this._splitIconName(this.svgIcon);
this._mdIconRegistry.getNamedSvgIcon(iconName, namespace).subscribe(
this._mdIconRegistry.getNamedSvgIcon(iconName, namespace).first().subscribe(
svg => this._setSvgElement(svg),
(err: any) => console.log(`Error retrieving icon: ${err}`));
} else if (this.svgSrc) {
this._mdIconRegistry.getSvgIconFromUrl(this.svgSrc).subscribe(
this._mdIconRegistry.getSvgIconFromUrl(this.svgSrc).first().subscribe(
svg => this._setSvgElement(svg),
(err: any) => console.log(`Error retrieving icon: ${err}`));
}
Expand Down
11 changes: 9 additions & 2 deletions src/lib/input/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Input,
Directive,
AfterContentInit,
OnDestroy,
ContentChild,
SimpleChange,
ContentChildren,
Expand All @@ -26,6 +27,7 @@ import {
import {CommonModule} from '@angular/common';
import {BooleanFieldValue, MdError} from '../core';
import {Observable} from 'rxjs/Observable';
import {Subscription} from 'rxjs/Subscription';


const noop = () => {};
Expand Down Expand Up @@ -104,7 +106,7 @@ export class MdHint {
host: {'(click)' : 'focus()'},
encapsulation: ViewEncapsulation.None,
})
export class MdInput implements ControlValueAccessor, AfterContentInit, OnChanges {
export class MdInput implements ControlValueAccessor, AfterContentInit, OnChanges, OnDestroy {
private _focused: boolean = false;
private _value: any = '';

Expand Down Expand Up @@ -166,6 +168,7 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange

private _blurEmitter: EventEmitter<FocusEvent> = new EventEmitter<FocusEvent>();
private _focusEmitter: EventEmitter<FocusEvent> = new EventEmitter<FocusEvent>();
private _hintChildrenChangesSubscription: Subscription;

@Output('blur')
get onBlur(): Observable<FocusEvent> {
Expand Down Expand Up @@ -248,7 +251,7 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange
this._validateConstraints();

// Trigger validation when the hint children change.
this._hintChildren.changes.subscribe(() => {
this._hintChildrenChangesSubscription = this._hintChildren.changes.subscribe(() => {
this._validateConstraints();
});
}
Expand All @@ -258,6 +261,10 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange
this._validateConstraints();
}

ngOnDestroy() {
this._hintChildrenChangesSubscription.unsubscribe();
}

/**
* Convert the value passed in to a value that is expected from the type of the md-input.
* This is normally performed by the *_VALUE_ACCESSOR in forms, but since the type is bound
Expand Down
5 changes: 5 additions & 0 deletions src/lib/list/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ElementRef,
Renderer,
AfterContentInit,
OnDestroy,
NgModule,
ModuleWithProviders,
} from '@angular/core';
Expand Down Expand Up @@ -62,6 +63,10 @@ export class MdListItem implements AfterContentInit {
this._lineSetter = new MdLineSetter(this._lines, this._renderer, this._element);
}

ngOnDestroy() {
this._lineSetter.destroy();
}

_handleFocus() {
this._hasFocus = true;
}
Expand Down
14 changes: 11 additions & 3 deletions src/lib/sidenav/sidenav.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
NgModule,
ModuleWithProviders,
AfterContentInit,
OnDestroy,
Component,
ContentChildren,
ElementRef,
Expand All @@ -17,6 +18,7 @@ import {
} from '@angular/core';
import {CommonModule} from '@angular/common';
import {Dir, MdError} from '../core';
import {Subscription} from 'rxjs/Subscription';

/** Exception thrown when two MdSidenav are matching the same side. */
export class MdDuplicatedSidenavError extends MdError {
Expand Down Expand Up @@ -66,7 +68,6 @@ export class MdSidenav {
/** Event emitted when the sidenav is fully closed. */
@Output('close') onClose = new EventEmitter<void>();


/**
* @param _elementRef The DOM element reference. Used for transition and width calculation.
* If not available we do not hook on transitions.
Expand Down Expand Up @@ -240,12 +241,14 @@ export class MdSidenav {
],
encapsulation: ViewEncapsulation.None,
})
export class MdSidenavLayout implements AfterContentInit {
export class MdSidenavLayout implements AfterContentInit, OnDestroy {
@ContentChildren(MdSidenav) _sidenavs: QueryList<MdSidenav>;

get start() { return this._start; }
get end() { return this._end; }

private _sidenavChangesSubscription: Subscription;

/** The sidenav at the start/end alignment, independent of direction. */
private _start: MdSidenav;
private _end: MdSidenav;
Expand All @@ -271,11 +274,16 @@ export class MdSidenavLayout implements AfterContentInit {
/** TODO: internal */
ngAfterContentInit() {
// On changes, assert on consistency.
this._sidenavs.changes.subscribe(() => this._validateDrawers());
this._sidenavChangesSubscription = this._sidenavs.changes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one also shouldn't be necessary because the QueryList is destroyed when the component is destroyed

.subscribe(() => this._validateDrawers());
this._sidenavs.forEach((sidenav: MdSidenav) => this._watchSidenavToggle(sidenav));
this._validateDrawers();
}

ngOnDestroy() {
this._sidenavChangesSubscription.unsubscribe();
}

/*
* Subscribes to sidenav events in order to set a class on the main layout element when the sidenav
* is open and the backdrop is visible. This ensures any overflow on the layout element is properly
Expand Down