parent
32157115da
commit
2fce701ced
|
@ -15,8 +15,8 @@ import {QueryList} from '../linker';
|
|||
import {Sanitizer} from '../sanitization/security';
|
||||
import {StyleSanitizeFn} from '../sanitization/style_sanitizer';
|
||||
import {Type} from '../type';
|
||||
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../util/ng_reflect';
|
||||
import {noop} from '../util/noop';
|
||||
|
||||
import {assertDefined, assertEqual, assertLessThan, assertNotEqual} from './assert';
|
||||
import {attachPatchData, getComponentViewByInstance} from './context_discovery';
|
||||
import {diPublicInInjector, getNodeInjectable, getOrCreateInjectable, getOrCreateNodeInjectorForNode, injectAttributeImpl} from './di';
|
||||
|
@ -956,6 +956,9 @@ export function elementProperty<T>(
|
|||
if (inputData && (dataValue = inputData[propName])) {
|
||||
setInputsForProperty(viewData, dataValue, value);
|
||||
if (isComponent(tNode)) markDirtyIfOnPush(viewData, index + HEADER_OFFSET);
|
||||
if (ngDevMode && tNode.type === TNodeType.Element) {
|
||||
setNgReflectProperties(element as RElement, propName, value);
|
||||
}
|
||||
} else if (tNode.type === TNodeType.Element) {
|
||||
const renderer = getRenderer();
|
||||
// It is assumed that the sanitizer is only added when the compiler determines that the property
|
||||
|
@ -1025,6 +1028,15 @@ function setInputsForProperty(viewData: LViewData, inputs: PropertyAliasValue, v
|
|||
}
|
||||
}
|
||||
|
||||
function setNgReflectProperties(element: RElement, propName: string, value: any) {
|
||||
const renderer = getRenderer() as ProceduralRenderer3;
|
||||
const isProcedural = isProceduralRenderer(renderer);
|
||||
const attrName = normalizeDebugBindingName(propName);
|
||||
const debugValue = normalizeDebugBindingValue(value);
|
||||
isProcedural ? renderer.setAttribute(element, attrName, debugValue) :
|
||||
element.setAttribute(attrName, debugValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Consolidates all inputs or outputs of all directives on this logical node.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* @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 function normalizeDebugBindingName(name: string) {
|
||||
// Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
|
||||
name = camelCaseToDashCase(name.replace(/[$@]/g, '_'));
|
||||
return `ng-reflect-${name}`;
|
||||
}
|
||||
|
||||
const CAMEL_CASE_REGEXP = /([A-Z])/g;
|
||||
|
||||
function camelCaseToDashCase(input: string): string {
|
||||
return input.replace(CAMEL_CASE_REGEXP, (...m: any[]) => '-' + m[1].toLowerCase());
|
||||
}
|
||||
|
||||
export function normalizeDebugBindingValue(value: any): string {
|
||||
try {
|
||||
// Limit the size of the value as otherwise the DOM just gets polluted.
|
||||
return value != null ? value.toString().slice(0, 30) : value;
|
||||
} catch (e) {
|
||||
return '[ERROR] Exception while trying to serialize the value';
|
||||
}
|
||||
}
|
|
@ -18,14 +18,13 @@ import {NgModuleRef} from '../linker/ng_module_factory';
|
|||
import {Renderer2, RendererFactory2, RendererStyleFlags2, RendererType2} from '../render/api';
|
||||
import {Sanitizer} from '../sanitization/security';
|
||||
import {Type} from '../type';
|
||||
import {tokenKey} from '../view/util';
|
||||
|
||||
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../util/ng_reflect';
|
||||
import {isViewDebugError, viewDestroyedError, viewWrappedDebugError} from './errors';
|
||||
import {resolveDep} from './provider';
|
||||
import {dirtyParentQueries, getQueryValue} from './query';
|
||||
import {createInjector, createNgModuleRef, getComponentViewDefinitionFactory} from './refs';
|
||||
import {ArgumentType, BindingFlags, CheckType, DebugContext, ElementData, NgModuleDefinition, NodeDef, NodeFlags, NodeLogger, ProviderOverride, RootData, Services, ViewData, ViewDefinition, ViewState, asElementData, asPureExpressionData} from './types';
|
||||
import {NOOP, isComponentView, renderNode, resolveDefinition, splitDepsDsl, viewParentEl} from './util';
|
||||
import {NOOP, isComponentView, renderNode, resolveDefinition, splitDepsDsl, tokenKey, viewParentEl} from './util';
|
||||
import {checkAndUpdateNode, checkAndUpdateView, checkNoChangesNode, checkNoChangesView, createComponentView, createEmbeddedView, createRootView, destroyView} from './view';
|
||||
|
||||
|
||||
|
@ -467,27 +466,6 @@ function debugCheckNoChangesNode(
|
|||
(<any>checkNoChangesNode)(view, nodeDef, argStyle, ...values);
|
||||
}
|
||||
|
||||
function normalizeDebugBindingName(name: string) {
|
||||
// Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
|
||||
name = camelCaseToDashCase(name.replace(/[$@]/g, '_'));
|
||||
return `ng-reflect-${name}`;
|
||||
}
|
||||
|
||||
const CAMEL_CASE_REGEXP = /([A-Z])/g;
|
||||
|
||||
function camelCaseToDashCase(input: string): string {
|
||||
return input.replace(CAMEL_CASE_REGEXP, (...m: any[]) => '-' + m[1].toLowerCase());
|
||||
}
|
||||
|
||||
function normalizeDebugBindingValue(value: any): string {
|
||||
try {
|
||||
// Limit the size of the value as otherwise the DOM just gets polluted.
|
||||
return value != null ? value.toString().slice(0, 30) : value;
|
||||
} catch (e) {
|
||||
return '[ERROR] Exception while trying to serialize the value';
|
||||
}
|
||||
}
|
||||
|
||||
function nextDirectiveWithBinding(view: ViewData, nodeIndex: number): number|null {
|
||||
for (let i = nodeIndex; i < view.def.nodes.length; i++) {
|
||||
const nodeDef = view.def.nodes[i];
|
||||
|
|
|
@ -218,11 +218,11 @@ export function resetDOM() {
|
|||
export function renderToHtml(
|
||||
template: ComponentTemplate<any>, ctx: any, consts: number = 0, vars: number = 0,
|
||||
directives?: DirectiveTypesOrFactory | null, pipes?: PipeTypesOrFactory | null,
|
||||
providedRendererFactory?: RendererFactory3 | null) {
|
||||
providedRendererFactory?: RendererFactory3 | null, keepNgReflect = false) {
|
||||
hostView = renderTemplate(
|
||||
containerEl, template, consts, vars, ctx, providedRendererFactory || testRendererFactory,
|
||||
hostView, toDefs(directives, extractDirectiveDef), toDefs(pipes, extractPipeDef));
|
||||
return toHtml(containerEl);
|
||||
return toHtml(containerEl, keepNgReflect);
|
||||
}
|
||||
|
||||
function toDefs(
|
||||
|
@ -263,7 +263,7 @@ export function renderComponent<T>(type: ComponentType<T>, opts?: CreateComponen
|
|||
/**
|
||||
* @deprecated use `TemplateFixture` or `ComponentFixture`
|
||||
*/
|
||||
export function toHtml<T>(componentOrElement: T | RElement): string {
|
||||
export function toHtml<T>(componentOrElement: T | RElement, keepNgReflect = false): string {
|
||||
let element: any;
|
||||
if (isComponentInstance(componentOrElement)) {
|
||||
const context = getContext(componentOrElement);
|
||||
|
@ -273,13 +273,17 @@ export function toHtml<T>(componentOrElement: T | RElement): string {
|
|||
}
|
||||
|
||||
if (element) {
|
||||
return stringifyElement(element)
|
||||
.replace(/^<div host="">(.*)<\/div>$/, '$1')
|
||||
.replace(/^<div fixture="mark">(.*)<\/div>$/, '$1')
|
||||
.replace(/^<div host="mark">(.*)<\/div>$/, '$1')
|
||||
.replace(' style=""', '')
|
||||
.replace(/<!--container-->/g, '')
|
||||
.replace(/<!--ng-container-->/g, '');
|
||||
let html = stringifyElement(element)
|
||||
.replace(/^<div host="">(.*)<\/div>$/, '$1')
|
||||
.replace(/^<div fixture="mark">(.*)<\/div>$/, '$1')
|
||||
.replace(/^<div host="mark">(.*)<\/div>$/, '$1')
|
||||
.replace(' style=""', '')
|
||||
.replace(/<!--container-->/g, '')
|
||||
.replace(/<!--ng-container-->/g, '');
|
||||
if (!keepNgReflect) {
|
||||
html = html.replace(/\sng-reflect-\S*="[^"]*"/g, '');
|
||||
}
|
||||
return html;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
|
|
|
@ -614,15 +614,14 @@ class HiddenModule {
|
|||
});
|
||||
}));
|
||||
|
||||
fixmeIvy('to investigate') &&
|
||||
it('should handle false values on attributes', async(() => {
|
||||
renderModule(FalseAttributesModule, {document: doc}).then(output => {
|
||||
expect(output).toBe(
|
||||
'<html><head></head><body><app ng-version="0.0.0-PLACEHOLDER">' +
|
||||
'<my-child ng-reflect-attr="false">Works!</my-child></app></body></html>');
|
||||
called = true;
|
||||
});
|
||||
}));
|
||||
it('should handle false values on attributes', async(() => {
|
||||
renderModule(FalseAttributesModule, {document: doc}).then(output => {
|
||||
expect(output).toBe(
|
||||
'<html><head></head><body><app ng-version="0.0.0-PLACEHOLDER">' +
|
||||
'<my-child ng-reflect-attr="false">Works!</my-child></app></body></html>');
|
||||
called = true;
|
||||
});
|
||||
}));
|
||||
|
||||
it('should handle element property "name"', async(() => {
|
||||
renderModule(NameModule, {document: doc}).then(output => {
|
||||
|
|
Loading…
Reference in New Issue