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:

committed by
Kara Erickson

parent
d5d9971c28
commit
ae0253f34a
@ -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;
|
||||
|
10
packages/core/src/render3/namespaces.ts
Normal file
10
packages/core/src/render3/namespaces.ts
Normal 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/';
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user