From b88f0ae171bc9186fa94c9efae6f916cd22ecefc Mon Sep 17 00:00:00 2001 From: crisbeto Date: Tue, 16 Jan 2018 22:03:25 +0100 Subject: [PATCH] fix(menu,toolbar): avoid potential server-side rendering errors Avoids a couple of potential server-side rendering errors due to the menu item and toolbar components referring to the `Node` global variable directly. --- src/lib/menu/menu-item.ts | 13 +++++++++++-- src/lib/toolbar/toolbar.ts | 15 ++++++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/lib/menu/menu-item.ts b/src/lib/menu/menu-item.ts index 188ae27d8a02..5c8d81c82cf3 100644 --- a/src/lib/menu/menu-item.ts +++ b/src/lib/menu/menu-item.ts @@ -13,6 +13,7 @@ import { ElementRef, OnDestroy, ViewEncapsulation, + Inject, } from '@angular/core'; import { CanDisable, @@ -21,6 +22,7 @@ import { mixinDisableRipple } from '@angular/material/core'; import {Subject} from 'rxjs/Subject'; +import {DOCUMENT} from '@angular/common'; // Boilerplate for applying mixins to MatMenuItem. /** @docs-private */ @@ -55,6 +57,8 @@ export const _MatMenuItemMixinBase = mixinDisableRipple(mixinDisabled(MatMenuIte export class MatMenuItem extends _MatMenuItemMixinBase implements FocusableOption, CanDisable, CanDisableRipple, OnDestroy { + private _document: Document; + /** Stream that emits when the menu item is hovered. */ _hovered: Subject = new Subject(); @@ -66,8 +70,10 @@ export class MatMenuItem extends _MatMenuItemMixinBase constructor( private _elementRef: ElementRef, - // TODO(crisbeto): switch to a required param when doing breaking changes. + @Inject(DOCUMENT) document?: any, private _focusMonitor?: FocusMonitor) { + + // @deletion-target 6.0.0 make `_focusMonitor` and `document` required params. super(); if (_focusMonitor) { @@ -76,6 +82,8 @@ export class MatMenuItem extends _MatMenuItemMixinBase // mouse or touch interaction. _focusMonitor.monitor(this._getHostElement(), false); } + + this._document = document; } /** Focuses the menu item. */ @@ -123,6 +131,7 @@ export class MatMenuItem extends _MatMenuItemMixinBase /** Gets the label to be used when determining whether the option should be focused. */ getLabel(): string { const element: HTMLElement = this._elementRef.nativeElement; + const textNodeType = this._document ? this._document.TEXT_NODE : 3; let output = ''; if (element.childNodes) { @@ -132,7 +141,7 @@ export class MatMenuItem extends _MatMenuItemMixinBase // We skip anything that's not a text node to prevent the text from // being thrown off by something like an icon. for (let i = 0; i < length; i++) { - if (element.childNodes[i].nodeType === Node.TEXT_NODE) { + if (element.childNodes[i].nodeType === textNodeType) { output += element.childNodes[i].textContent; } } diff --git a/src/lib/toolbar/toolbar.ts b/src/lib/toolbar/toolbar.ts index 2da02fbf50af..51f063aaeb6a 100644 --- a/src/lib/toolbar/toolbar.ts +++ b/src/lib/toolbar/toolbar.ts @@ -15,10 +15,12 @@ import { ElementRef, isDevMode, QueryList, - ViewEncapsulation + ViewEncapsulation, + Inject, } from '@angular/core'; import {CanColor, mixinColor} from '@angular/material/core'; import {Platform} from '@angular/cdk/platform'; +import {DOCUMENT} from '@angular/common'; // Boilerplate for applying mixins to MatToolbar. /** @docs-private */ @@ -51,12 +53,19 @@ export class MatToolbarRow {} preserveWhitespaces: false, }) export class MatToolbar extends _MatToolbarMixinBase implements CanColor, AfterViewInit { + private _document: Document; /** Reference to all toolbar row elements that have been projected. */ @ContentChildren(MatToolbarRow) _toolbarRows: QueryList; - constructor(elementRef: ElementRef, private _platform: Platform) { + constructor( + elementRef: ElementRef, + private _platform: Platform, + @Inject(DOCUMENT) document?: any) { super(elementRef); + + // TODO: make the document a required param when doing breaking changes. + this._document = document; } ngAfterViewInit() { @@ -80,7 +89,7 @@ export class MatToolbar extends _MatToolbarMixinBase implements CanColor, AfterV // a element. const isCombinedUsage = [].slice.call(this._elementRef.nativeElement.childNodes) .filter(node => !(node.classList && node.classList.contains('mat-toolbar-row'))) - .filter(node => node.nodeType !== Node.COMMENT_NODE) + .filter(node => node.nodeType !== (this._document ? this._document.COMMENT_NODE : 8)) .some(node => node.textContent.trim()); if (isCombinedUsage) {