fix(ivy): set namespace for host elements of dynamically created components (#35136)

Prior to this change, element namespace was not set for host elements of dynamically created components that resulted in incorrect rendering in a browser. This commit adds the logic to pick and set correct namespace for host element when component is created dynamically.

PR Close #35136
This commit is contained in:
Andrew Kushnir
2020-02-03 18:02:03 -08:00
committed by Kara Erickson
parent d5d9971c28
commit ae0253f34a
6 changed files with 127 additions and 12 deletions

View File

@ -19,6 +19,7 @@ import {RendererFactory2} from '../render/api';
import {Sanitizer} from '../sanitization/sanitizer';
import {VERSION} from '../version';
import {NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR} from '../view/provider';
import {assertComponentType} from './assert';
import {LifecycleHooksFeature, createRootComponent, createRootComponentView, createRootContext} from './component';
import {getComponentDef} from './definition';
@ -28,6 +29,7 @@ import {ComponentDef} from './interfaces/definition';
import {TContainerNode, TElementContainerNode, TElementNode} from './interfaces/node';
import {RNode, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
import {LView, LViewFlags, TVIEW, TViewType} from './interfaces/view';
import {MATH_ML_NAMESPACE, SVG_NAMESPACE} from './namespaces';
import {stringifyCSSSelectorList} from './node_selector_matcher';
import {enterView, leaveView} from './state';
import {defaultScheduler} from './util/misc_utils';
@ -59,6 +61,11 @@ function toRefArray(map: {[key: string]: string}): {propName: string; templateNa
return array;
}
function getNamespace(elementName: string): string|null {
const name = elementName.toLowerCase();
return name === 'svg' ? SVG_NAMESPACE : (name === 'math' ? MATH_ML_NAMESPACE : null);
}
/**
* A change detection scheduler token for {@link RootContext}. This token is the default value used
* for the default `RootContext` found in the {@link ROOT_CONTEXT} token.
@ -132,14 +139,14 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
const sanitizer = rootViewInjector.get(Sanitizer, null);
const hostRenderer = rendererFactory.createRenderer(null, this.componentDef);
// Determine a tag name used for creating host elements when this component is created
// dynamically. Default to 'div' if this component did not specify any tag name in its selector.
const elementName = this.componentDef.selectors[0][0] as string || 'div';
const hostRNode = rootSelectorOrNode ?
locateHostElement(hostRenderer, rootSelectorOrNode, this.componentDef.encapsulation) :
// Determine a tag name used for creating host elements when this component is created
// dynamically. Default to 'div' if this component did not specify any tag name in its
// selector.
elementCreate(
this.componentDef.selectors[0][0] as string || 'div',
rendererFactory.createRenderer(null, this.componentDef), null);
elementName, rendererFactory.createRenderer(null, this.componentDef),
getNamespace(elementName));
const rootFlags = this.componentDef.onPush ? LViewFlags.Dirty | LViewFlags.IsRoot :
LViewFlags.CheckAlways | LViewFlags.IsRoot;

View File

@ -0,0 +1,10 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
export const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
export const MATH_ML_NAMESPACE = 'http://www.w3.org/1998/MathML/';

View File

@ -11,6 +11,7 @@ import {assertDefined} from '../util/assert';
import {assertLViewOrUndefined} from './assert';
import {TNode} from './interfaces/node';
import {CONTEXT, DECLARATION_VIEW, LView, OpaqueViewState, TVIEW, TView} from './interfaces/view';
import {MATH_ML_NAMESPACE, SVG_NAMESPACE} from './namespaces';
/**
@ -511,7 +512,7 @@ export function setSelectedIndex(index: number) {
* @codeGenApi
*/
export function ɵɵnamespaceSVG() {
instructionState.lFrame.currentNamespace = 'http://www.w3.org/2000/svg';
instructionState.lFrame.currentNamespace = SVG_NAMESPACE;
}
/**
@ -520,7 +521,7 @@ export function ɵɵnamespaceSVG() {
* @codeGenApi
*/
export function ɵɵnamespaceMathML() {
instructionState.lFrame.currentNamespace = 'http://www.w3.org/1998/MathML/';
instructionState.lFrame.currentNamespace = MATH_ML_NAMESPACE;
}
/**