refactor(ivy): remove directive references from template (#22986)
PR Close #22986
This commit is contained in:
parent
2aabbc51fa
commit
910a16a1ff
|
@ -17,7 +17,7 @@ export class LargeTableComponent {
|
|||
/** @nocollapse */
|
||||
static ngComponentDef: ComponentDef<LargeTableComponent> = defineComponent({
|
||||
type: LargeTableComponent,
|
||||
tag: 'largetable',
|
||||
selector: [[['largetable'], null]],
|
||||
template: function(ctx: LargeTableComponent, cm: boolean) {
|
||||
if (cm) {
|
||||
E(0, 'table');
|
||||
|
|
|
@ -37,7 +37,7 @@ export class TreeComponent {
|
|||
/** @nocollapse */
|
||||
static ngComponentDef: ComponentDef<TreeComponent> = defineComponent({
|
||||
type: TreeComponent,
|
||||
tag: 'tree',
|
||||
selector: [[['tree'], null]],
|
||||
template: function(ctx: TreeComponent, cm: boolean) {
|
||||
if (cm) {
|
||||
E(0, 'span');
|
||||
|
@ -54,7 +54,7 @@ export class TreeComponent {
|
|||
let cm0 = V(0);
|
||||
{
|
||||
if (cm0) {
|
||||
E(0, TreeComponent);
|
||||
E(0, 'tree');
|
||||
e();
|
||||
}
|
||||
p(0, 'data', b(ctx.data.left));
|
||||
|
@ -69,7 +69,7 @@ export class TreeComponent {
|
|||
let cm0 = V(0);
|
||||
{
|
||||
if (cm0) {
|
||||
E(0, TreeComponent);
|
||||
E(0, 'tree');
|
||||
e();
|
||||
}
|
||||
p(0, 'data', b(ctx.data.right));
|
||||
|
@ -80,7 +80,8 @@ export class TreeComponent {
|
|||
cr();
|
||||
},
|
||||
factory: () => new TreeComponent,
|
||||
inputs: {data: 'data'}
|
||||
inputs: {data: 'data'},
|
||||
directiveDefs: () => [TreeComponent.ngComponentDef]
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -90,7 +91,7 @@ export class TreeFunction {
|
|||
/** @nocollapse */
|
||||
static ngComponentDef: ComponentDef<TreeFunction> = defineComponent({
|
||||
type: TreeFunction,
|
||||
tag: 'tree',
|
||||
selector: [[['tree'], null]],
|
||||
template: function(ctx: TreeFunction, cm: boolean) {
|
||||
// bit of a hack
|
||||
TreeTpl(ctx.data, cm);
|
||||
|
|
|
@ -60,6 +60,9 @@ export function compileDirective(
|
|||
// e.g. 'type: MyDirective`
|
||||
field('type', outputCtx.importExpr(directive.type.reference));
|
||||
|
||||
// e.g. `selector: [[[null, 'someDir', ''], null]]`
|
||||
field('selector', createDirectiveSelector(directive.selector !));
|
||||
|
||||
// e.g. `factory: () => new MyApp(injectElementRef())`
|
||||
field('factory', createFactory(directive.type, outputCtx, reflector, directive.queries));
|
||||
|
||||
|
@ -118,13 +121,11 @@ export function compileComponent(
|
|||
// e.g. `type: MyApp`
|
||||
field('type', outputCtx.importExpr(component.type.reference));
|
||||
|
||||
// e.g. `tag: 'my-app'`
|
||||
// This is optional and only included if the first selector of a component has element.
|
||||
// e.g. `selector: [[['my-app'], null]]`
|
||||
field('selector', createDirectiveSelector(component.selector !));
|
||||
|
||||
const selector = component.selector && CssSelector.parse(component.selector);
|
||||
const firstSelector = selector && selector[0];
|
||||
if (firstSelector && firstSelector.hasElementSelector()) {
|
||||
field('tag', o.literal(firstSelector.element));
|
||||
}
|
||||
|
||||
// e.g. `attr: ["class", ".my.app"]
|
||||
// This is optional an only included if the first selector of a component specifies attributes.
|
||||
|
@ -916,6 +917,11 @@ type HostBindings = {
|
|||
[key: string]: string
|
||||
};
|
||||
|
||||
// Turn a directive selector into an R3-compatible selector for directive def
|
||||
function createDirectiveSelector(selector: string): o.Expression {
|
||||
return asLiteral(parseSelectorsToR3Selector(CssSelector.parse(selector)));
|
||||
}
|
||||
|
||||
function createHostAttributesArray(
|
||||
directiveMetadata: CompileDirectiveMetadata, outputCtx: OutputContext): o.Expression|null {
|
||||
const values: o.Expression[] = [];
|
||||
|
|
|
@ -92,11 +92,12 @@ describe('compiler compliance', () => {
|
|||
const ChildComponentDefinition = `
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: ChildComponent,
|
||||
tag: 'child',
|
||||
selector: [[['child'], null]],
|
||||
factory: function ChildComponent_Factory() { return new ChildComponent(); },
|
||||
template: function ChildComponent_Template(ctx: IDENT, cm: IDENT) {
|
||||
if (cm) {
|
||||
$r3$.ɵT(0, 'child-view');
|
||||
|
||||
}
|
||||
}
|
||||
});`;
|
||||
|
@ -105,6 +106,7 @@ describe('compiler compliance', () => {
|
|||
const SomeDirectiveDefinition = `
|
||||
static ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: SomeDirective,
|
||||
selector: [[[null, 'some-directive', ''], null]],
|
||||
factory: function SomeDirective_Factory() {return new SomeDirective(); }
|
||||
});
|
||||
`;
|
||||
|
@ -116,7 +118,7 @@ describe('compiler compliance', () => {
|
|||
…
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: function MyComponent_Factory() { return new MyComponent(); },
|
||||
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
|
||||
if (cm) {
|
||||
|
@ -161,6 +163,7 @@ describe('compiler compliance', () => {
|
|||
const HostBindingDirDeclaration = `
|
||||
static ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: HostBindingDir,
|
||||
selector: [[[null, 'hostBindingDir', ''], null]],
|
||||
factory: function HostBindingDir_Factory() { return new HostBindingDir(); },
|
||||
hostBindings: function HostBindingDir_HostBindings(
|
||||
dirIndex: $number$, elIndex: $number$) {
|
||||
|
@ -203,6 +206,7 @@ describe('compiler compliance', () => {
|
|||
const IfDirectiveDefinition = `
|
||||
static ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: IfDirective,
|
||||
selector: [[[null, 'if', ''], null]],
|
||||
factory: function IfDirective_Factory() { return new IfDirective($r3$.ɵinjectTemplateRef()); }
|
||||
});`;
|
||||
const MyComponentDefinition = `
|
||||
|
@ -211,7 +215,7 @@ describe('compiler compliance', () => {
|
|||
…
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: function MyComponent_Factory() { return new MyComponent(); },
|
||||
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
|
||||
if (cm) {
|
||||
|
@ -283,7 +287,7 @@ describe('compiler compliance', () => {
|
|||
…
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -361,7 +365,7 @@ describe('compiler compliance', () => {
|
|||
…
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -421,7 +425,7 @@ describe('compiler compliance', () => {
|
|||
…
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -485,7 +489,7 @@ describe('compiler compliance', () => {
|
|||
…
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -542,7 +546,7 @@ describe('compiler compliance', () => {
|
|||
const SimpleComponentDefinition = `
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: SimpleComponent,
|
||||
tag: 'simple',
|
||||
selector: [[['simple'], null]],
|
||||
factory: function SimpleComponent_Factory() { return new SimpleComponent(); },
|
||||
template: function SimpleComponent_Template(ctx: IDENT, cm: IDENT) {
|
||||
if (cm) {
|
||||
|
@ -561,7 +565,7 @@ describe('compiler compliance', () => {
|
|||
…
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: ComplexComponent,
|
||||
tag: 'complex',
|
||||
selector: [[['complex'], null]],
|
||||
factory: function ComplexComponent_Factory() { return new ComplexComponent(); },
|
||||
template: function ComplexComponent_Template(ctx: IDENT, cm: IDENT) {
|
||||
if (cm) {
|
||||
|
@ -627,7 +631,7 @@ describe('compiler compliance', () => {
|
|||
…
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: ViewQueryComponent,
|
||||
tag: 'view-query-component',
|
||||
selector: [[['view-query-component'], null]],
|
||||
factory: function ViewQueryComponent_Factory() { return new ViewQueryComponent(); },
|
||||
template: function ViewQueryComponent_Template(ctx: $ViewQueryComponent$, cm: $boolean$) {
|
||||
var $tmp$: $any$;
|
||||
|
@ -685,7 +689,7 @@ describe('compiler compliance', () => {
|
|||
const ContentQueryComponentDefinition = `
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: ContentQueryComponent,
|
||||
tag: 'content-query-component',
|
||||
selector: [[['content-query-component'], null]],
|
||||
factory: function ContentQueryComponent_Factory() {
|
||||
return [new ContentQueryComponent(), $r3$.ɵQ(null, SomeDirective, true)];
|
||||
},
|
||||
|
@ -768,7 +772,7 @@ describe('compiler compliance', () => {
|
|||
…
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: IDENT, cm: IDENT) {
|
||||
if (cm) {
|
||||
|
@ -809,7 +813,7 @@ describe('compiler compliance', () => {
|
|||
…
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: function MyComponent_Factory() { return new MyComponent(); },
|
||||
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
|
||||
if (cm) {
|
||||
|
@ -877,7 +881,7 @@ describe('compiler compliance', () => {
|
|||
const LifecycleCompDefinition = `
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: LifecycleComp,
|
||||
tag: 'lifecycle-comp',
|
||||
selector: [[['lifecycle-comp'], null]],
|
||||
factory: function LifecycleComp_Factory() { return new LifecycleComp(); },
|
||||
template: function LifecycleComp_Template(ctx: IDENT, cm: IDENT) {},
|
||||
inputs: {nameMin: 'name'},
|
||||
|
@ -889,7 +893,7 @@ describe('compiler compliance', () => {
|
|||
…
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: SimpleLayout,
|
||||
tag: 'simple-layout',
|
||||
selector: [[['simple-layout'], null]],
|
||||
factory: function SimpleLayout_Factory() { return new SimpleLayout(); },
|
||||
template: function SimpleLayout_Template(ctx: IDENT, cm: IDENT) {
|
||||
if (cm) {
|
||||
|
@ -997,6 +1001,7 @@ describe('compiler compliance', () => {
|
|||
const ForDirectiveDefinition = `
|
||||
static ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: ForOfDirective,
|
||||
selector: [[[null, 'forOf', ''], null]],
|
||||
factory: function ForOfDirective_Factory() {
|
||||
return new ForOfDirective($r3$.ɵinjectViewContainerRef(), $r3$.ɵinjectTemplateRef());
|
||||
},
|
||||
|
@ -1010,7 +1015,7 @@ describe('compiler compliance', () => {
|
|||
…
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: function MyComponent_Factory() { return new MyComponent(); },
|
||||
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
|
||||
if (cm) {
|
||||
|
@ -1088,7 +1093,7 @@ describe('compiler compliance', () => {
|
|||
…
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: function MyComponent_Factory() { return new MyComponent(); },
|
||||
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
|
||||
if (cm) {
|
||||
|
@ -1141,4 +1146,4 @@ describe('compiler compliance', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@ import {ComponentRef as viewEngine_ComponentRef} from '../linker/component_facto
|
|||
|
||||
import {assertComponentType, assertNotNull} from './assert';
|
||||
import {queueInitHooks, queueLifecycleHooks} from './hooks';
|
||||
import {CLEAN_PROMISE, _getComponentHostLElementNode, baseDirectiveCreate, createLView, createTView, enterView, getRootView, hostElement, initChangeDetectorIfExisting, locateHostElement, renderComponentOrTemplate} from './instructions';
|
||||
import {CLEAN_PROMISE, ROOT_DIRECTIVE_INDICES, _getComponentHostLElementNode, baseDirectiveCreate, createLView, createTView, detectChangesInternal, enterView, executeInitAndContentHooks, getRootView, hostElement, initChangeDetectorIfExisting, leaveView, locateHostElement, setHostBindings} from './instructions';
|
||||
import {ComponentDef, ComponentType} from './interfaces/definition';
|
||||
import {LElementNode, TNodeFlags} from './interfaces/node';
|
||||
import {RElement, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
|
||||
|
@ -123,7 +123,9 @@ export function renderComponent<T>(
|
|||
const componentDef = (componentType as ComponentType<T>).ngComponentDef as ComponentDef<T>;
|
||||
if (componentDef.type != componentType) componentDef.type = componentType;
|
||||
let component: T;
|
||||
const hostNode = locateHostElement(rendererFactory, opts.host || componentDef.tag);
|
||||
// TODO: Replace when flattening CssSelector type
|
||||
const componentTag = componentDef.selector ![0] ![0] ![0];
|
||||
const hostNode = locateHostElement(rendererFactory, opts.host || componentTag);
|
||||
const rootContext: RootContext = {
|
||||
// Incomplete initialization due to circular reference.
|
||||
component: null !,
|
||||
|
@ -131,28 +133,32 @@ export function renderComponent<T>(
|
|||
clean: CLEAN_PROMISE,
|
||||
};
|
||||
const rootView = createLView(
|
||||
-1, rendererFactory.createRenderer(hostNode, componentDef.rendererType), createTView(), null,
|
||||
rootContext, componentDef.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways);
|
||||
-1, rendererFactory.createRenderer(hostNode, componentDef.rendererType), createTView(null),
|
||||
null, rootContext, componentDef.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways);
|
||||
|
||||
const oldView = enterView(rootView, null !);
|
||||
|
||||
let elementNode: LElementNode;
|
||||
try {
|
||||
if (rendererFactory.begin) rendererFactory.begin();
|
||||
|
||||
// Create element node at index 0 in data array
|
||||
elementNode = hostElement(hostNode, componentDef);
|
||||
elementNode = hostElement(componentTag, hostNode, componentDef);
|
||||
|
||||
// Create directive instance with factory() and store at index 0 in directives array
|
||||
component = rootContext.component =
|
||||
baseDirectiveCreate(0, componentDef.factory(), componentDef) as T;
|
||||
initChangeDetectorIfExisting(elementNode.nodeInjector, component);
|
||||
initChangeDetectorIfExisting(elementNode.nodeInjector, component, elementNode.data !);
|
||||
|
||||
opts.hostFeatures && opts.hostFeatures.forEach((feature) => feature(component, componentDef));
|
||||
|
||||
executeInitAndContentHooks();
|
||||
setHostBindings(ROOT_DIRECTIVE_INDICES);
|
||||
detectChangesInternal(elementNode.data as LView, elementNode, componentDef, component);
|
||||
} finally {
|
||||
// We must not use leaveView here because it will set creationMode to false too early,
|
||||
// causing init-only hooks not to run. The detectChanges call below will execute
|
||||
// leaveView at the appropriate time in the lifecycle.
|
||||
enterView(oldView, null);
|
||||
leaveView(oldView);
|
||||
if (rendererFactory.end) rendererFactory.end();
|
||||
}
|
||||
|
||||
opts.hostFeatures && opts.hostFeatures.forEach((feature) => feature(component, componentDef));
|
||||
renderComponentOrTemplate(elementNode, rootView, component);
|
||||
return component;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,8 @@ import {Type} from '../type';
|
|||
import {resolveRendererType2} from '../view/util';
|
||||
|
||||
import {diPublic} from './di';
|
||||
import {ComponentDef, ComponentDefFeature, ComponentTemplate, DirectiveDef, DirectiveDefFeature, PipeDef} from './interfaces/definition';
|
||||
import {ComponentDef, ComponentDefFeature, ComponentTemplate, DirectiveDef, DirectiveDefFeature, DirectiveDefListOrFactory, PipeDef} from './interfaces/definition';
|
||||
import {CssSelector} from './interfaces/projection';
|
||||
|
||||
|
||||
|
||||
|
@ -41,6 +42,9 @@ export function defineComponent<T>(componentDefinition: {
|
|||
*/
|
||||
type: Type<T>;
|
||||
|
||||
/** The selector that will be used to match nodes to this component. */
|
||||
selector: CssSelector;
|
||||
|
||||
/**
|
||||
* Factory method used to create an instance of directive.
|
||||
*/
|
||||
|
@ -90,11 +94,6 @@ export function defineComponent<T>(componentDefinition: {
|
|||
*/
|
||||
exportAs?: string;
|
||||
|
||||
/**
|
||||
* HTML tag name to use in place where this component should be instantiated.
|
||||
*/
|
||||
tag: string;
|
||||
|
||||
/**
|
||||
* Template function use for rendering DOM.
|
||||
*
|
||||
|
@ -147,13 +146,20 @@ export function defineComponent<T>(componentDefinition: {
|
|||
* Defines the set of injectable objects that are visible to its view DOM children.
|
||||
*/
|
||||
viewProviders?: Provider[];
|
||||
|
||||
/**
|
||||
* Registry of directives and components that may be found in this component's view.
|
||||
*
|
||||
* The property is either an array of `DirectiveDef`s or a function which returns the array of
|
||||
* `DirectiveDef`s. The function is necessary to be able to support forward declarations.
|
||||
*/
|
||||
directiveDefs?: DirectiveDefListOrFactory | null;
|
||||
}): ComponentDef<T> {
|
||||
const type = componentDefinition.type;
|
||||
const def = <ComponentDef<any>>{
|
||||
type: type,
|
||||
diPublic: null,
|
||||
factory: componentDefinition.factory,
|
||||
tag: componentDefinition.tag || null !,
|
||||
template: componentDefinition.template || null !,
|
||||
hostBindings: componentDefinition.hostBindings || null,
|
||||
attributes: componentDefinition.attributes || null,
|
||||
|
@ -168,7 +174,9 @@ export function defineComponent<T>(componentDefinition: {
|
|||
afterViewInit: type.prototype.ngAfterViewInit || null,
|
||||
afterViewChecked: type.prototype.ngAfterViewChecked || null,
|
||||
onDestroy: type.prototype.ngOnDestroy || null,
|
||||
onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush
|
||||
onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush,
|
||||
directiveDefs: componentDefinition.directiveDefs || null,
|
||||
selector: componentDefinition.selector
|
||||
};
|
||||
const feature = componentDefinition.features;
|
||||
feature && feature.forEach((fn) => fn(def));
|
||||
|
@ -300,6 +308,9 @@ export const defineDirective = defineComponent as any as<T>(directiveDefinition:
|
|||
*/
|
||||
type: Type<T>;
|
||||
|
||||
/** The selector that will be used to match nodes to this directive. */
|
||||
selector: CssSelector;
|
||||
|
||||
/**
|
||||
* Factory method used to create an instance of directive.
|
||||
*/
|
||||
|
|
|
@ -19,7 +19,7 @@ import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, ViewRef as viewEngine_Vie
|
|||
import {Type} from '../type';
|
||||
|
||||
import {assertLessThan, assertNotNull} from './assert';
|
||||
import {assertPreviousIsParent, getDirectiveInstance, getPreviousOrParentNode, getRenderer, renderEmbeddedTemplate} from './instructions';
|
||||
import {assertPreviousIsParent, enterView, getDirectiveInstance, getPreviousOrParentNode, getRenderer, isComponent, renderEmbeddedTemplate} from './instructions';
|
||||
import {ComponentTemplate, DirectiveDef} from './interfaces/definition';
|
||||
import {LInjector} from './interfaces/injector';
|
||||
import {LContainerNode, LElementNode, LNode, LNodeType, LViewNode, TNodeFlags} from './interfaces/node';
|
||||
|
@ -299,12 +299,10 @@ export function getOrCreateChangeDetectorRef(
|
|||
if (di.changeDetectorRef) return di.changeDetectorRef;
|
||||
|
||||
const currentNode = di.node;
|
||||
if (currentNode.data === null) {
|
||||
// if data is null, this node is a regular element node (not a component)
|
||||
return di.changeDetectorRef = getOrCreateHostChangeDetector(currentNode.view.node);
|
||||
} else if (currentNode.type === LNodeType.Element) {
|
||||
// if it's an element node with data, it's a component and context will be set later
|
||||
if (isComponent(currentNode.tNode !)) {
|
||||
return di.changeDetectorRef = createViewRef(currentNode.data as LView, context);
|
||||
} else if (currentNode.type === LNodeType.Element) {
|
||||
return di.changeDetectorRef = getOrCreateHostChangeDetector(currentNode.view.node);
|
||||
}
|
||||
return null !;
|
||||
}
|
||||
|
@ -388,7 +386,7 @@ export function getOrCreateInjectable<T>(
|
|||
// The size of the node's directive's list is stored in certain bits of the node's flags,
|
||||
// so exact it with a mask and shift it back such that the bits reflect the real value.
|
||||
const flags = node.tNode !.flags;
|
||||
const size = flags & TNodeFlags.SIZE_MASK;
|
||||
const size = (flags & TNodeFlags.SIZE_MASK) >> TNodeFlags.SIZE_SHIFT;
|
||||
|
||||
if (size !== 0) {
|
||||
// The start index of the directives list is also part of the node's flags, but there is
|
||||
|
@ -574,6 +572,9 @@ class ViewContainerRef implements viewEngine_ViewContainerRef {
|
|||
createEmbeddedView<C>(
|
||||
templateRef: viewEngine_TemplateRef<C>, context?: C|undefined,
|
||||
index?: number|undefined): viewEngine_EmbeddedViewRef<C> {
|
||||
// set current view to container node's view
|
||||
enterView(this._node.view, null);
|
||||
|
||||
const viewRef = templateRef.createEmbeddedView(context !);
|
||||
this.insert(viewRef, index);
|
||||
return viewRef;
|
||||
|
|
|
@ -45,7 +45,8 @@ export function queueLifecycleHooks(flags: number, currentView: LView): void {
|
|||
const tView = currentView.tView;
|
||||
if (tView.firstTemplatePass === true) {
|
||||
const start = flags >> TNodeFlags.INDX_SHIFT;
|
||||
const end = start + (flags & TNodeFlags.SIZE_MASK);
|
||||
const size = (flags & TNodeFlags.SIZE_MASK) >> TNodeFlags.SIZE_SHIFT;
|
||||
const end = start + size;
|
||||
|
||||
// It's necessary to loop through the directives at elementEnd() (rather than processing in
|
||||
// directiveCreate) so we can preserve the current hook order. Content, view, and destroy
|
||||
|
|
|
@ -18,8 +18,8 @@ import {LView, LViewFlags, LifecycleStage, RootContext, TData, TView} from './in
|
|||
import {LContainerNode, LElementNode, LNode, LNodeType, TNodeFlags, LProjectionNode, LTextNode, LViewNode, TNode, TContainerNode, InitialInputData, InitialInputs, PropertyAliases, PropertyAliasValue,} from './interfaces/node';
|
||||
import {assertNodeType} from './node_assert';
|
||||
import {appendChild, insertChild, insertView, appendProjectedNode, removeView, canInsertNativeNode} from './node_manipulation';
|
||||
import {matchingSelectorIndex} from './node_selector_matcher';
|
||||
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveType} from './interfaces/definition';
|
||||
import {isNodeMatchingSelector, matchingSelectorIndex} from './node_selector_matcher';
|
||||
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefList, DirectiveDefListOrFactory, DirectiveType} from './interfaces/definition';
|
||||
import {RElement, RText, Renderer3, RendererFactory3, ProceduralRenderer3, ObjectOrientedRenderer3, RendererStyleFlags3, isProceduralRenderer} from './interfaces/renderer';
|
||||
import {isDifferent, stringify} from './util';
|
||||
import {executeHooks, queueLifecycleHooks, queueInitHooks, executeInitHooks} from './hooks';
|
||||
|
@ -48,7 +48,7 @@ export type Sanitizer = (value: any) => string;
|
|||
*
|
||||
* Saved here to avoid re-instantiating an array on every change detection run.
|
||||
*/
|
||||
const rootDirectiveIndices = [0, 0];
|
||||
export const _ROOT_DIRECTIVE_INDICES = [0, 0];
|
||||
|
||||
|
||||
/**
|
||||
|
@ -243,7 +243,7 @@ function refreshDirectives() {
|
|||
}
|
||||
|
||||
/** Sets the host bindings for the current view. */
|
||||
function setHostBindings(bindings: number[] | null): void {
|
||||
export function setHostBindings(bindings: number[] | null): void {
|
||||
if (bindings != null) {
|
||||
const defs = currentView.tView.directives !;
|
||||
for (let i = 0; i < bindings.length; i += 2) {
|
||||
|
@ -263,7 +263,7 @@ function refreshChildComponents(components: number[] | null): void {
|
|||
}
|
||||
}
|
||||
|
||||
function executeInitAndContentHooks(): void {
|
||||
export function executeInitAndContentHooks(): void {
|
||||
if (!checkNoChangesMode) {
|
||||
const tView = currentView.tView;
|
||||
executeInitHooks(currentView, tView, creationMode);
|
||||
|
@ -395,21 +395,25 @@ function resetApplicationState() {
|
|||
|
||||
/**
|
||||
*
|
||||
* @param host Existing node to render into.
|
||||
* @param hostNode Existing node to render into.
|
||||
* @param template Template function with the instructions.
|
||||
* @param context to pass into the template.
|
||||
* @param providedRendererFactory renderer factory to use
|
||||
* @param host The host element node to use
|
||||
* @param directiveRegistry Any directive defs that should be used to match nodes to directives
|
||||
*/
|
||||
export function renderTemplate<T>(
|
||||
hostNode: RElement, template: ComponentTemplate<T>, context: T,
|
||||
providedRendererFactory: RendererFactory3, host: LElementNode | null): LElementNode {
|
||||
providedRendererFactory: RendererFactory3, host: LElementNode | null,
|
||||
directiveRegistry: DirectiveDefListOrFactory | null = null): LElementNode {
|
||||
if (host == null) {
|
||||
resetApplicationState();
|
||||
rendererFactory = providedRendererFactory;
|
||||
host = createLNode(
|
||||
null, LNodeType.Element, hostNode,
|
||||
createLView(
|
||||
-1, providedRendererFactory.createRenderer(null, null), getOrCreateTView(template),
|
||||
null, {}, LViewFlags.CheckAlways));
|
||||
-1, providedRendererFactory.createRenderer(null, null),
|
||||
getOrCreateTView(template, directiveRegistry), null, {}, LViewFlags.CheckAlways));
|
||||
}
|
||||
const hostView = host.data !;
|
||||
ngDevMode && assertNotNull(hostView, 'Host node should have an LView defined in host.data.');
|
||||
|
@ -427,8 +431,9 @@ export function renderEmbeddedTemplate<T>(
|
|||
previousOrParentNode = null !;
|
||||
let cm: boolean = false;
|
||||
if (viewNode == null) {
|
||||
const view =
|
||||
createLView(-1, renderer, createTView(), template, context, LViewFlags.CheckAlways);
|
||||
const view = createLView(
|
||||
-1, renderer, createTView(currentView.tView.directiveRegistry), template, context,
|
||||
LViewFlags.CheckAlways);
|
||||
viewNode = createLNode(null, LNodeType.View, null, view);
|
||||
cm = true;
|
||||
}
|
||||
|
@ -460,7 +465,7 @@ export function renderComponentOrTemplate<T>(
|
|||
|
||||
// Element was stored at 0 in data and directive was stored at 0 in directives
|
||||
// in renderComponent()
|
||||
setHostBindings(rootDirectiveIndices);
|
||||
setHostBindings(_ROOT_DIRECTIVE_INDICES);
|
||||
componentRefresh(0, 0);
|
||||
}
|
||||
} finally {
|
||||
|
@ -479,9 +484,8 @@ export function renderComponentOrTemplate<T>(
|
|||
* Create DOM element. The instruction must later be followed by `elementEnd()` call.
|
||||
*
|
||||
* @param index Index of the element in the data array
|
||||
* @param nameOrComponentType Name of the DOM Node or `ComponentType` to create.
|
||||
* @param name Name of the DOM Node
|
||||
* @param attrs Statically bound set of attributes to be written into the DOM element on creation.
|
||||
* @param directiveTypes A set of directives declared on this element.
|
||||
* @param localRefs A set of local reference bindings on the element.
|
||||
*
|
||||
* Attributes and localRefs are passed as an array of strings where elements with an even index
|
||||
|
@ -489,77 +493,71 @@ export function renderComponentOrTemplate<T>(
|
|||
* ['id', 'warning5', 'class', 'alert']
|
||||
*/
|
||||
export function elementStart(
|
||||
index: number, nameOrComponentType?: string | ComponentType<any>, attrs?: string[] | null,
|
||||
directiveTypes?: DirectiveType<any>[] | null, localRefs?: string[] | null): RElement {
|
||||
index: number, name?: string, attrs?: string[] | null, localRefs?: string[] | null): RElement {
|
||||
let node: LElementNode;
|
||||
let native: RElement;
|
||||
|
||||
if (nameOrComponentType == null) {
|
||||
if (name == null) {
|
||||
// native node retrieval - used for exporting elements as tpl local variables (<div #foo>)
|
||||
const node = data[index] !;
|
||||
native = node && (node as LElementNode).native;
|
||||
} else {
|
||||
ngDevMode &&
|
||||
assertNull(currentView.bindingStartIndex, 'elements should be created before any bindings');
|
||||
const isHostElement = typeof nameOrComponentType !== 'string';
|
||||
|
||||
let hostComponentDef: ComponentDef<any>|null = null;
|
||||
let name = nameOrComponentType as string;
|
||||
native = renderer.createElement(name);
|
||||
node = createLNode(index, LNodeType.Element, native !, null);
|
||||
|
||||
let directiveIndex = getNextDirectiveIndex(index);
|
||||
if (attrs) setUpAttributes(native, attrs);
|
||||
appendChild(node.parent !, native, currentView);
|
||||
|
||||
if (isHostElement) {
|
||||
hostComponentDef = firstTemplatePass ?
|
||||
(nameOrComponentType as ComponentType<any>).ngComponentDef :
|
||||
currentView.tView.directives ![directiveIndex] as ComponentDef<any>;
|
||||
if (firstTemplatePass) {
|
||||
const tNode = createTNode(name, attrs || null, null, null);
|
||||
cacheMatchingDirectivesForNode(tNode);
|
||||
|
||||
name = hostComponentDef !.tag;
|
||||
}
|
||||
|
||||
if (name === null) {
|
||||
// TODO: future support for nameless components.
|
||||
throw 'for now name is required';
|
||||
} else {
|
||||
native = renderer.createElement(name);
|
||||
|
||||
let componentView: LView|null = null;
|
||||
if (isHostElement) {
|
||||
const tView = getOrCreateTView(hostComponentDef !.template);
|
||||
const hostView = createLView(
|
||||
-1, rendererFactory.createRenderer(native, hostComponentDef !.rendererType), tView,
|
||||
null, null, hostComponentDef !.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways);
|
||||
componentView = addToViewTree(hostView);
|
||||
}
|
||||
|
||||
// Only component views should be added to the view tree directly. Embedded views are
|
||||
// accessed through their containers because they may be removed / re-added later.
|
||||
node = createLNode(index, LNodeType.Element, native, componentView);
|
||||
|
||||
if (node.tNode == null) {
|
||||
const localNames: (string | number)[]|null = findMatchingLocalNames(
|
||||
hostComponentDef, localRefs, isHostElement ? directiveIndex : -1, '');
|
||||
ngDevMode && assertDataInRange(index - 1);
|
||||
node.tNode = tData[index] = createTNode(name, attrs || null, null, localNames);
|
||||
}
|
||||
|
||||
if (attrs) setUpAttributes(native, attrs);
|
||||
appendChild(node.parent !, native, currentView);
|
||||
|
||||
if (hostComponentDef) {
|
||||
// TODO(mhevery): This assumes that the directives come in correct order, which
|
||||
// is not guaranteed. Must be refactored to take it into account.
|
||||
const instance = hostComponentDef.factory();
|
||||
directiveCreate(directiveIndex, index, instance, hostComponentDef, null);
|
||||
initChangeDetectorIfExisting(node.nodeInjector, instance);
|
||||
queueComponentIndexForCheck(directiveIndex, index);
|
||||
directiveIndex++;
|
||||
}
|
||||
hack_declareDirectives(directiveIndex, index, directiveTypes, localRefs);
|
||||
ngDevMode && assertDataInRange(index - 1);
|
||||
node.tNode = tData[index] = tNode;
|
||||
|
||||
if (!isComponent(tNode)) {
|
||||
tNode.localNames = findMatchingLocalNames(null, localRefs, -1, '');
|
||||
}
|
||||
}
|
||||
hack_declareDirectives(index, localRefs);
|
||||
}
|
||||
return native;
|
||||
}
|
||||
|
||||
function cacheMatchingDirectivesForNode(tNode: TNode): void {
|
||||
const registry = currentView.tView.directiveRegistry;
|
||||
const startIndex = directives ? directives.length : 0;
|
||||
|
||||
if (registry) {
|
||||
let componentFlag = 0;
|
||||
let size = 0;
|
||||
|
||||
for (let i = 0; i < registry.length; i++) {
|
||||
const def = registry[i];
|
||||
if (isNodeMatchingSelector(tNode, def.selector !)) {
|
||||
if ((def as ComponentDef<any>).template) {
|
||||
if (componentFlag) throwMultipleComponentError(tNode);
|
||||
componentFlag |= TNodeFlags.Component;
|
||||
}
|
||||
(currentView.tView.directives || (currentView.tView.directives = [])).push(def);
|
||||
size++;
|
||||
}
|
||||
}
|
||||
if (size > 0) buildTNodeFlags(tNode, startIndex, size, componentFlag);
|
||||
}
|
||||
}
|
||||
|
||||
function buildTNodeFlags(tNode: TNode, index: number, size: number, component: number): void {
|
||||
tNode.flags = (index << TNodeFlags.INDX_SHIFT) | (size << TNodeFlags.SIZE_SHIFT) | component;
|
||||
}
|
||||
|
||||
function throwMultipleComponentError(tNode: TNode): never {
|
||||
throw new Error(`Multiple components match node with tagname ${tNode.tagName}`);
|
||||
}
|
||||
|
||||
/** Stores index of component's host element so it will be queued for view refresh during CD. */
|
||||
function queueComponentIndexForCheck(dirIndex: number, elIndex: number): void {
|
||||
if (firstTemplatePass) {
|
||||
|
@ -576,30 +574,35 @@ function queueHostBindingForCheck(dirIndex: number, elIndex: number): void {
|
|||
}
|
||||
|
||||
/** Sets the context for a ChangeDetectorRef to the given instance. */
|
||||
export function initChangeDetectorIfExisting(injector: LInjector | null, instance: any): void {
|
||||
export function initChangeDetectorIfExisting(
|
||||
injector: LInjector | null, instance: any, view: LView): void {
|
||||
if (injector && injector.changeDetectorRef != null) {
|
||||
(injector.changeDetectorRef as ViewRef<any>)._setComponentContext(instance);
|
||||
(injector.changeDetectorRef as ViewRef<any>)._setComponentContext(view, instance);
|
||||
}
|
||||
}
|
||||
|
||||
export function isComponent(tNode: TNode): boolean {
|
||||
return (tNode.flags & TNodeFlags.Component) === TNodeFlags.Component;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function instantiates the given directives. It is a hack since it assumes the directives
|
||||
* come in the correct order for DI.
|
||||
*/
|
||||
function hack_declareDirectives(
|
||||
index: number, elementIndex: number, directiveTypes: DirectiveType<any>[] | null | undefined,
|
||||
localRefs: string[] | null | undefined, ) {
|
||||
if (directiveTypes) {
|
||||
const defs = currentView.tView.directives !;
|
||||
function hack_declareDirectives(elementIndex: number, localRefs: string[] | null | undefined) {
|
||||
const size = (previousOrParentNode.tNode !.flags & TNodeFlags.SIZE_MASK) >> TNodeFlags.SIZE_SHIFT;
|
||||
|
||||
if (size > 0) {
|
||||
let startIndex = previousOrParentNode.tNode !.flags >> TNodeFlags.INDX_SHIFT;
|
||||
const endIndex = startIndex + size;
|
||||
const tDirectives = currentView.tView.directives !;
|
||||
|
||||
// TODO(mhevery): This assumes that the directives come in correct order, which
|
||||
// is not guaranteed. Must be refactored to take it into account.
|
||||
for (let i = 0; i < directiveTypes.length; i++) {
|
||||
const directiveType = directiveTypes[i];
|
||||
const directiveDef =
|
||||
firstTemplatePass ? directiveType.ngDirectiveDef : defs[index] as DirectiveDef<any>;
|
||||
directiveCreate(index, elementIndex, directiveDef.factory(), directiveDef, localRefs);
|
||||
index++;
|
||||
for (let i = startIndex; i < endIndex; i++) {
|
||||
const def = tDirectives[i] as DirectiveDef<any>;
|
||||
directiveCreate(elementIndex, def.factory(), def, localRefs);
|
||||
startIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -633,12 +636,13 @@ function findMatchingLocalNames(
|
|||
* @param template The template from which to get static data
|
||||
* @returns TView
|
||||
*/
|
||||
function getOrCreateTView(template: ComponentTemplate<any>): TView {
|
||||
return template.ngPrivateData || (template.ngPrivateData = createTView() as never);
|
||||
function getOrCreateTView(
|
||||
template: ComponentTemplate<any>, defs: DirectiveDefListOrFactory | null): TView {
|
||||
return template.ngPrivateData || (template.ngPrivateData = createTView(defs) as never);
|
||||
}
|
||||
|
||||
/** Creates a TView instance */
|
||||
export function createTView(): TView {
|
||||
export function createTView(defs: DirectiveDefListOrFactory | null): TView {
|
||||
return {
|
||||
data: [],
|
||||
directives: null,
|
||||
|
@ -652,7 +656,8 @@ export function createTView(): TView {
|
|||
destroyHooks: null,
|
||||
pipeDestroyHooks: null,
|
||||
hostBindings: null,
|
||||
components: null
|
||||
components: null,
|
||||
directiveRegistry: typeof defs === 'function' ? defs() : defs
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -708,13 +713,22 @@ export function locateHostElement(
|
|||
*
|
||||
* @returns LElementNode created
|
||||
*/
|
||||
export function hostElement(rNode: RElement | null, def: ComponentDef<any>): LElementNode {
|
||||
export function hostElement(
|
||||
tag: string, rNode: RElement | null, def: ComponentDef<any>): LElementNode {
|
||||
resetApplicationState();
|
||||
const node = createLNode(
|
||||
0, LNodeType.Element, rNode, createLView(
|
||||
-1, renderer, getOrCreateTView(def.template), null, null,
|
||||
def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways));
|
||||
if (firstTemplatePass) node.tNode = createTNode(def.tag, null, null, null);
|
||||
0, LNodeType.Element, rNode,
|
||||
createLView(
|
||||
-1, renderer, getOrCreateTView(def.template, def.directiveDefs), null, null,
|
||||
def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways));
|
||||
|
||||
if (firstTemplatePass) {
|
||||
node.tNode = createTNode(tag as string, null, null, null);
|
||||
// Root directive is stored at index 0, size 1
|
||||
buildTNodeFlags(node.tNode, 0, 1, TNodeFlags.Component);
|
||||
currentView.tView.directives = [def];
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -898,7 +912,7 @@ function setInputsForProperty(inputs: PropertyAliasValue, value: any): void {
|
|||
*/
|
||||
function generatePropertyAliases(
|
||||
tNodeFlags: TNodeFlags, direction: BindingDirection): PropertyAliases|null {
|
||||
const size = tNodeFlags & TNodeFlags.SIZE_MASK;
|
||||
const size = (tNodeFlags & TNodeFlags.SIZE_MASK) >> TNodeFlags.SIZE_SHIFT;
|
||||
let propStore: PropertyAliases|null = null;
|
||||
|
||||
if (size > 0) {
|
||||
|
@ -1101,20 +1115,25 @@ export function textBinding<T>(index: number, value: T | NO_CHANGE): void {
|
|||
* NOTE: directives can be created in order other than the index order. They can also
|
||||
* be retrieved before they are created in which case the value will be null.
|
||||
*
|
||||
* @param index Index to save the directive in the directives array
|
||||
* @param elementIndex Index of the host element in the data array
|
||||
* @param directive The directive instance.
|
||||
* @param directiveDef DirectiveDef object which contains information about the template.
|
||||
* @param localRefs Names under which a query can retrieve the directive instance
|
||||
*/
|
||||
export function directiveCreate<T>(
|
||||
index: number, elementIndex: number, directive: T, directiveDef: DirectiveDef<T>,
|
||||
elementIndex: number, directive: T, directiveDef: DirectiveDef<T>| ComponentDef<T>,
|
||||
localRefs?: string[] | null): T {
|
||||
const index = directives ? directives.length : 0;
|
||||
const instance = baseDirectiveCreate(index, directive, directiveDef);
|
||||
|
||||
ngDevMode && assertNotNull(previousOrParentNode.tNode, 'previousOrParentNode.tNode');
|
||||
const tNode: TNode|null = previousOrParentNode.tNode !;
|
||||
|
||||
const isComponent = (directiveDef as ComponentDef<any>).template;
|
||||
if (isComponent) {
|
||||
addComponentLogic(index, elementIndex, directive, directiveDef as ComponentDef<any>);
|
||||
}
|
||||
|
||||
if (firstTemplatePass) {
|
||||
// Init hooks are queued now so ngOnInit is called in host components before
|
||||
// any projected components.
|
||||
|
@ -1123,7 +1142,8 @@ export function directiveCreate<T>(
|
|||
if (directiveDef.hostBindings) queueHostBindingForCheck(index, elementIndex);
|
||||
|
||||
if (localRefs) {
|
||||
const localNames = findMatchingLocalNames(directiveDef, localRefs, index);
|
||||
const localNames =
|
||||
findMatchingLocalNames(directiveDef, localRefs, index, isComponent ? '' : undefined);
|
||||
tNode.localNames =
|
||||
localNames && tNode.localNames ? tNode.localNames.concat(localNames) : localNames;
|
||||
}
|
||||
|
@ -1136,6 +1156,26 @@ export function directiveCreate<T>(
|
|||
return instance;
|
||||
}
|
||||
|
||||
function addComponentLogic<T>(
|
||||
index: number, elementIndex: number, instance: T, def: ComponentDef<any>): void {
|
||||
const tView = getOrCreateTView(def.template, def.directiveDefs);
|
||||
|
||||
// Only component views should be added to the view tree directly. Embedded views are
|
||||
// accessed through their containers because they may be removed / re-added later.
|
||||
const hostView = addToViewTree(createLView(
|
||||
-1, rendererFactory.createRenderer(previousOrParentNode.native as RElement, def.rendererType),
|
||||
tView, null, null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways));
|
||||
|
||||
(previousOrParentNode.data as any) = hostView;
|
||||
(hostView.node as any) = previousOrParentNode;
|
||||
|
||||
initChangeDetectorIfExisting(previousOrParentNode.nodeInjector, instance, hostView);
|
||||
|
||||
if (firstTemplatePass) {
|
||||
queueComponentIndexForCheck(index, elementIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A lighter version of directiveCreate() that is used for the root component
|
||||
*
|
||||
|
@ -1143,7 +1183,7 @@ export function directiveCreate<T>(
|
|||
* current Angular. Example: local refs and inputs on root component.
|
||||
*/
|
||||
export function baseDirectiveCreate<T>(
|
||||
index: number, directive: T, directiveDef: DirectiveDef<T>): T {
|
||||
index: number, directive: T, directiveDef: DirectiveDef<T>| ComponentDef<any>): T {
|
||||
ngDevMode &&
|
||||
assertNull(currentView.bindingStartIndex, 'directives should be created before any bindings');
|
||||
ngDevMode && assertPreviousIsParent();
|
||||
|
@ -1156,17 +1196,6 @@ export function baseDirectiveCreate<T>(
|
|||
ngDevMode && assertDataNext(index, directives);
|
||||
directives[index] = directive;
|
||||
|
||||
if (firstTemplatePass) {
|
||||
const defs = currentView.tView.directives || (currentView.tView.directives = []);
|
||||
|
||||
ngDevMode && assertDataNext(index, defs);
|
||||
defs[index] = (directiveDef);
|
||||
|
||||
const flags = previousOrParentNode.tNode !.flags;
|
||||
previousOrParentNode.tNode !.flags =
|
||||
(flags & TNodeFlags.SIZE_MASK) === 0 ? (index << TNodeFlags.INDX_SHIFT) | 1 : flags + 1;
|
||||
}
|
||||
|
||||
const diPublic = directiveDef !.diPublic;
|
||||
if (diPublic) {
|
||||
diPublic(directiveDef !);
|
||||
|
@ -1253,8 +1282,8 @@ function generateInitialInputs(
|
|||
* @param localRefs A set of local reference bindings on the element.
|
||||
*/
|
||||
export function container(
|
||||
index: number, directiveTypes?: DirectiveType<any>[], template?: ComponentTemplate<any>,
|
||||
tagName?: string, attrs?: string[], localRefs?: string[] | null): void {
|
||||
index: number, template?: ComponentTemplate<any>, tagName?: string, attrs?: string[],
|
||||
localRefs?: string[] | null): void {
|
||||
ngDevMode &&
|
||||
assertNull(
|
||||
currentView.bindingStartIndex, 'container nodes should be created before any bindings');
|
||||
|
@ -1285,7 +1314,9 @@ export function container(
|
|||
// Containers are added to the current view tree instead of their embedded views
|
||||
// because views can be removed and re-inserted.
|
||||
addToViewTree(node.data);
|
||||
hack_declareDirectives(getNextDirectiveIndex(index), index, directiveTypes, localRefs);
|
||||
|
||||
if (firstTemplatePass) cacheMatchingDirectivesForNode(node.tNode);
|
||||
hack_declareDirectives(index, localRefs);
|
||||
|
||||
isParent = false;
|
||||
ngDevMode && assertNodeType(previousOrParentNode, LNodeType.Container);
|
||||
|
@ -1298,12 +1329,6 @@ export function container(
|
|||
}
|
||||
}
|
||||
|
||||
/** Retrieves the next directive index to write */
|
||||
function getNextDirectiveIndex(index: number): number {
|
||||
return firstTemplatePass ? (directives ? directives.length : 0) :
|
||||
(tData[index] as TNode).flags >> TNodeFlags.INDX_SHIFT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a container up to receive views.
|
||||
*
|
||||
|
@ -1421,7 +1446,6 @@ export function embeddedViewStart(viewBlockId: number): boolean {
|
|||
|
||||
enterView(newView, createLNode(null, LNodeType.View, null, newView));
|
||||
}
|
||||
|
||||
return !existingViewNode;
|
||||
}
|
||||
|
||||
|
@ -1441,7 +1465,7 @@ function getOrCreateEmbeddedTView(viewIndex: number, parent: LContainerNode): TV
|
|||
ngDevMode && assertNodeType(parent, LNodeType.Container);
|
||||
const tContainer = (parent !.tNode as TContainerNode).data;
|
||||
if (viewIndex >= tContainer.length || tContainer[viewIndex] == null) {
|
||||
tContainer[viewIndex] = createTView();
|
||||
tContainer[viewIndex] = createTView(currentView.tView.directiveRegistry);
|
||||
}
|
||||
return tContainer[viewIndex];
|
||||
}
|
||||
|
@ -1487,9 +1511,10 @@ export function componentRefresh<T>(directiveIndex: number, elementIndex: number
|
|||
// Only attached CheckAlways components or attached, dirty OnPush components should be checked
|
||||
if (viewAttached(hostView) && hostView.flags & (LViewFlags.CheckAlways | LViewFlags.Dirty)) {
|
||||
ngDevMode && assertDataInRange(directiveIndex, directives !);
|
||||
const template = (currentView.tView.directives ![directiveIndex] as ComponentDef<any>).template;
|
||||
const def = currentView.tView.directives ![directiveIndex] as ComponentDef<any>;
|
||||
|
||||
detectChangesInternal(
|
||||
hostView, element, template, getDirectiveInstance<T>(directives ![directiveIndex]));
|
||||
hostView, element, def, getDirectiveInstance<T>(directives ![directiveIndex]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1795,8 +1820,8 @@ export function detectChanges<T>(component: T): void {
|
|||
const hostNode = _getComponentHostLElementNode(component);
|
||||
ngDevMode && assertNotNull(hostNode.data, 'Component host node should be attached to an LView');
|
||||
const componentIndex = hostNode.tNode !.flags >> TNodeFlags.INDX_SHIFT;
|
||||
const template = (hostNode.view.tView.directives ![componentIndex] as ComponentDef<T>).template;
|
||||
detectChangesInternal(hostNode.data as LView, hostNode, template, component);
|
||||
const def = hostNode.view.tView.directives ![componentIndex] as ComponentDef<T>;
|
||||
detectChangesInternal(hostNode.data as LView, hostNode, def, component);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1833,8 +1858,10 @@ function throwErrorIfNoChangesMode(oldValue: any, currValue: any): never|void {
|
|||
|
||||
/** Checks the view of the component provided. Does not gate on dirty checks or execute doCheck. */
|
||||
export function detectChangesInternal<T>(
|
||||
hostView: LView, hostNode: LElementNode, template: ComponentTemplate<any>, component: T) {
|
||||
hostView: LView, hostNode: LElementNode, def: ComponentDef<any>, component: T) {
|
||||
const oldView = enterView(hostView, hostNode);
|
||||
const template = def.template;
|
||||
|
||||
try {
|
||||
template(component, creationMode);
|
||||
refreshDynamicChildren();
|
||||
|
@ -2150,3 +2177,4 @@ export function _getComponentHostLElementNode<T>(component: T): LElementNode {
|
|||
}
|
||||
|
||||
export const CLEAN_PROMISE = _CLEAN_PROMISE;
|
||||
export const ROOT_DIRECTIVE_INDICES = _ROOT_DIRECTIVE_INDICES;
|
||||
|
|
|
@ -12,7 +12,7 @@ import {Provider} from '../../core';
|
|||
import {RendererType2} from '../../render/api';
|
||||
import {Type} from '../../type';
|
||||
import {resolveRendererType2} from '../../view/util';
|
||||
|
||||
import {CssSelector} from './projection';
|
||||
|
||||
|
||||
/**
|
||||
|
@ -61,6 +61,9 @@ export interface DirectiveDef<T> {
|
|||
/** Function that makes a directive public to the DI system. */
|
||||
diPublic: ((def: DirectiveDef<any>) => void)|null;
|
||||
|
||||
/** The selector that will be used to match nodes to this directive. */
|
||||
selector: CssSelector;
|
||||
|
||||
/**
|
||||
* A dictionary mapping the inputs' minified property names to their public API names, which
|
||||
* are their aliases if any, or their original unminified property names
|
||||
|
@ -122,13 +125,6 @@ export interface DirectiveDef<T> {
|
|||
* See: {@link defineComponent}
|
||||
*/
|
||||
export interface ComponentDef<T> extends DirectiveDef<T> {
|
||||
/**
|
||||
* The tag name which should be used by the component.
|
||||
*
|
||||
* NOTE: only used with component directives.
|
||||
*/
|
||||
readonly tag: string;
|
||||
|
||||
/**
|
||||
* The View template of the component.
|
||||
*
|
||||
|
@ -157,6 +153,14 @@ export interface ComponentDef<T> extends DirectiveDef<T> {
|
|||
* children only.
|
||||
*/
|
||||
readonly viewProviders?: Provider[];
|
||||
|
||||
/**
|
||||
* Registry of directives and components that may be found in this view.
|
||||
*
|
||||
* The property is either an array of `DirectiveDef`s or a function which returns the array of
|
||||
* `DirectiveDef`s. The function is necessary to be able to support forward declarations.
|
||||
*/
|
||||
directiveDefs: DirectiveDefListOrFactory|null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -195,6 +199,15 @@ export interface PipeDef<T> {
|
|||
export type DirectiveDefFeature = <T>(directiveDef: DirectiveDef<T>) => void;
|
||||
export type ComponentDefFeature = <T>(componentDef: ComponentDef<T>) => void;
|
||||
|
||||
/**
|
||||
* Type used for directiveDefs on component definition.
|
||||
*
|
||||
* The function is necessary to be able to support forward declarations.
|
||||
*/
|
||||
export type DirectiveDefListOrFactory = (() => DirectiveDefList) | DirectiveDefList;
|
||||
|
||||
export type DirectiveDefList = (DirectiveDef<any>| ComponentDef<any>)[];
|
||||
|
||||
// Note: This hack is necessary so we don't erroneously get a circular dependency
|
||||
// failure based on types.
|
||||
export const unusedValueExportToPlacateAjd = 1;
|
||||
|
|
|
@ -32,7 +32,19 @@ export const enum LNodeType {
|
|||
* on how to map a particular set of bits to the node's first directive index
|
||||
* (with INDX_SHIFT) or the node's directive count (with SIZE_MASK)
|
||||
*/
|
||||
export const enum TNodeFlags {INDX_SHIFT = 12, SIZE_MASK = 0b00000000000000000000111111111111}
|
||||
export const enum TNodeFlags {
|
||||
/** Whether or not this node is a component */
|
||||
Component = 0b001,
|
||||
|
||||
/** How far to shift the flags to get the first directive index on this node */
|
||||
INDX_SHIFT = 13,
|
||||
|
||||
/** How far to shift the flags to get the number of directives on this node */
|
||||
SIZE_SHIFT = 1,
|
||||
|
||||
/** Mask to get the number of directives on this node */
|
||||
SIZE_MASK = 0b00000000000000000001111111111110
|
||||
}
|
||||
|
||||
/**
|
||||
* LNode is an internal data structure which is used for the incremental DOM algorithm.
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import {LContainer} from './container';
|
||||
import {ComponentDef, ComponentTemplate, DirectiveDef, PipeDef} from './definition';
|
||||
import {ComponentDef, ComponentTemplate, DirectiveDef, DirectiveDefList, PipeDef} from './definition';
|
||||
import {LElementNode, LViewNode, TNode} from './node';
|
||||
import {LQueries} from './query';
|
||||
import {Renderer3} from './renderer';
|
||||
|
@ -219,19 +219,31 @@ export interface LViewOrLContainer {
|
|||
* Stored on the template function as ngPrivateData.
|
||||
*/
|
||||
export interface TView {
|
||||
/** Whether or not this template has been processed. */
|
||||
firstTemplatePass: boolean;
|
||||
|
||||
/** Static data equivalent of LView.data[]. Contains TNodes. */
|
||||
data: TData;
|
||||
|
||||
/**
|
||||
* Directive and component defs for this view
|
||||
* Directive and component defs that have already been matched to nodes on
|
||||
* this view.
|
||||
*
|
||||
* Defs are stored at the same index in TView.directives[] as their instances
|
||||
* are stored in LView.directives[]. This simplifies lookup in DI.
|
||||
*/
|
||||
directives: (ComponentDef<any>|DirectiveDef<any>)[]|null;
|
||||
directives: DirectiveDefList|null;
|
||||
|
||||
/** Whether or not this template has been processed. */
|
||||
firstTemplatePass: boolean;
|
||||
/**
|
||||
* Full registry of directives and components that may be found in this view.
|
||||
*
|
||||
* The property is either an array of `DirectiveDef`s or a function which returns the array of
|
||||
* `DirectiveDef`s. The function is necessary to be able to support forward declarations.
|
||||
*
|
||||
* It's necessary to keep a copy of the full def list on the TView so it's possible
|
||||
* to render template functions without a host component.
|
||||
*/
|
||||
directiveRegistry: DirectiveDefList|null;
|
||||
|
||||
/**
|
||||
* Array of ngOnInit and ngDoCheck hooks that should be executed for this view in
|
||||
|
|
|
@ -196,8 +196,8 @@ function getIdxOfMatchingSelector(tNode: TNode, selector: string): number|null {
|
|||
function geIdxOfMatchingDirective(node: LNode, type: Type<any>): number|null {
|
||||
const defs = node.view.tView.directives !;
|
||||
const flags = node.tNode !.flags;
|
||||
for (let i = flags >> TNodeFlags.INDX_SHIFT, ii = i + (flags & TNodeFlags.SIZE_MASK); i < ii;
|
||||
i++) {
|
||||
const size = (flags & TNodeFlags.SIZE_MASK) >> TNodeFlags.SIZE_SHIFT;
|
||||
for (let i = flags >> TNodeFlags.INDX_SHIFT, ii = i + size; i < ii; i++) {
|
||||
const def = defs[i] as DirectiveDef<any>;
|
||||
if (def.diPublic && def.type === type) {
|
||||
return i;
|
||||
|
|
|
@ -21,7 +21,10 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T> {
|
|||
constructor(private _view: LView, context: T|null, ) { this.context = context !; }
|
||||
|
||||
/** @internal */
|
||||
_setComponentContext(context: T) { this.context = context; }
|
||||
_setComponentContext(view: LView, context: T) {
|
||||
this._view = view;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
destroy(): void { notImplemented(); }
|
||||
destroyed: boolean;
|
||||
|
@ -223,9 +226,9 @@ export class EmbeddedViewRef<T> extends ViewRef<T> {
|
|||
* @param context The context for this view
|
||||
* @returns The ViewRef
|
||||
*/
|
||||
export function createViewRef<T>(view: LView, context: T): ViewRef<T> {
|
||||
export function createViewRef<T>(view: LView | null, context: T): ViewRef<T> {
|
||||
// TODO: add detectChanges back in when implementing ChangeDetectorRef.detectChanges
|
||||
return addDestroyable(new ViewRef(view, context));
|
||||
return addDestroyable(new ViewRef(view !, context));
|
||||
}
|
||||
|
||||
/** Interface for destroy logic. Implemented by addDestroyable. */
|
||||
|
|
|
@ -44,6 +44,9 @@
|
|||
{
|
||||
"name": "QueueAction"
|
||||
},
|
||||
{
|
||||
"name": "ROOT_DIRECTIVE_INDICES"
|
||||
},
|
||||
{
|
||||
"name": "SafeSubscriber"
|
||||
},
|
||||
|
@ -107,6 +110,9 @@
|
|||
{
|
||||
"name": "baseDirectiveCreate"
|
||||
},
|
||||
{
|
||||
"name": "buildTNodeFlags"
|
||||
},
|
||||
{
|
||||
"name": "callHooks"
|
||||
},
|
||||
|
@ -239,9 +245,6 @@
|
|||
{
|
||||
"name": "renderComponent"
|
||||
},
|
||||
{
|
||||
"name": "renderComponentOrTemplate"
|
||||
},
|
||||
{
|
||||
"name": "renderEmbeddedTemplate"
|
||||
},
|
||||
|
@ -251,9 +254,6 @@
|
|||
{
|
||||
"name": "resolveRendererType2"
|
||||
},
|
||||
{
|
||||
"name": "rootDirectiveIndices"
|
||||
},
|
||||
{
|
||||
"name": "runIfPresent"
|
||||
},
|
||||
|
|
|
@ -34,7 +34,7 @@ describe('iv perf test', () => {
|
|||
class Component {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: Component,
|
||||
tag: 'div',
|
||||
selector: [[['div'], null]],
|
||||
template: function Template(ctx: any, cm: any) {
|
||||
if (cm) {
|
||||
container(0);
|
||||
|
|
|
@ -13,7 +13,7 @@ import {getRenderedText, whenRendered} from '../../src/render3/component';
|
|||
import {LifecycleHooksFeature, defineComponent, defineDirective, injectChangeDetectorRef} from '../../src/render3/index';
|
||||
import {bind, container, containerRefreshEnd, containerRefreshStart, detectChanges, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation2, listener, markDirty, text, textBinding, tick} from '../../src/render3/instructions';
|
||||
|
||||
import {containerEl, renderComponent, requestAnimationFrame} from './render_util';
|
||||
import {containerEl, createComponent, renderComponent, requestAnimationFrame} from './render_util';
|
||||
|
||||
describe('change detection', () => {
|
||||
|
||||
|
@ -25,7 +25,7 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-comp',
|
||||
selector: [[['my-comp'], null]],
|
||||
factory: () => new MyComponent(),
|
||||
template: (ctx: MyComponent, cm: boolean) => {
|
||||
if (cm) {
|
||||
|
@ -96,7 +96,7 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-comp',
|
||||
selector: [[['my-comp'], null]],
|
||||
factory: () => comp = new MyComponent(),
|
||||
/**
|
||||
* {{ doCheckCount }} - {{ name }}
|
||||
|
@ -123,16 +123,17 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: () => new MyApp(),
|
||||
/** <my-comp [name]="name"></my-comp> */
|
||||
template: (ctx: MyApp, cm: boolean) => {
|
||||
if (cm) {
|
||||
elementStart(0, MyComponent);
|
||||
elementStart(0, 'my-comp');
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'name', bind(ctx.name));
|
||||
}
|
||||
},
|
||||
directiveDefs: () => [MyComponent.ngComponentDef]
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -192,28 +193,18 @@ describe('change detection', () => {
|
|||
});
|
||||
|
||||
it('should not check OnPush components in update mode when parent events occur', () => {
|
||||
class ButtonParent {
|
||||
noop() {}
|
||||
function noop() {}
|
||||
|
||||
const ButtonParent = createComponent('button-parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'my-comp');
|
||||
elementEnd();
|
||||
elementStart(1, 'button', ['id', 'parent']);
|
||||
{ listener('click', () => noop()); }
|
||||
elementEnd();
|
||||
}
|
||||
}, [MyComponent.ngComponentDef]);
|
||||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: ButtonParent,
|
||||
tag: 'button-parent',
|
||||
factory: () => new ButtonParent(),
|
||||
/**
|
||||
* <my-comp></my-comp>
|
||||
* <button id="parent" (click)="noop()"></button>
|
||||
*/
|
||||
template: (ctx: ButtonParent, cm: boolean) => {
|
||||
if (cm) {
|
||||
elementStart(0, MyComponent);
|
||||
elementEnd();
|
||||
elementStart(1, 'button', ['id', 'parent']);
|
||||
{ listener('click', () => ctx.noop()); }
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
const buttonParent = renderComponent(ButtonParent);
|
||||
expect(getRenderedText(buttonParent)).toEqual('1 - Nancy');
|
||||
|
||||
|
@ -232,35 +223,28 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: ButtonParent,
|
||||
tag: 'button-parent',
|
||||
selector: [[['button-parent'], null]],
|
||||
factory: () => parent = new ButtonParent(),
|
||||
/** {{ doCheckCount }} - <my-comp></my-comp> */
|
||||
template: (ctx: ButtonParent, cm: boolean) => {
|
||||
if (cm) {
|
||||
text(0);
|
||||
elementStart(1, MyComponent);
|
||||
elementStart(1, 'my-comp');
|
||||
elementEnd();
|
||||
}
|
||||
textBinding(0, interpolation1('', ctx.doCheckCount, ' - '));
|
||||
},
|
||||
directiveDefs: () => [MyComponent.ngComponentDef],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
});
|
||||
}
|
||||
|
||||
class MyButtonApp {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyButtonApp,
|
||||
tag: 'my-button-app',
|
||||
factory: () => new MyButtonApp(),
|
||||
/** <button-parent></button-parent> */
|
||||
template: (ctx: MyButtonApp, cm: boolean) => {
|
||||
if (cm) {
|
||||
elementStart(0, ButtonParent);
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
const MyButtonApp = createComponent('my-button-app', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'button-parent');
|
||||
elementEnd();
|
||||
}
|
||||
}, [ButtonParent.ngComponentDef]);
|
||||
|
||||
const myButtonApp = renderComponent(MyButtonApp);
|
||||
expect(parent !.doCheckCount).toEqual(1);
|
||||
|
@ -298,7 +282,7 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyComp,
|
||||
tag: 'my-comp',
|
||||
selector: [[['my-comp'], null]],
|
||||
factory: () => myComp = new MyComp(injectChangeDetectorRef()),
|
||||
/** {{ name }} */
|
||||
template: (ctx: MyComp, cm: boolean) => {
|
||||
|
@ -320,7 +304,7 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: ParentComp,
|
||||
tag: 'parent-comp',
|
||||
selector: [[['parent-comp'], null]],
|
||||
factory: () => new ParentComp(injectChangeDetectorRef()),
|
||||
/**
|
||||
* {{ doCheckCount}} -
|
||||
|
@ -329,19 +313,23 @@ describe('change detection', () => {
|
|||
template: (ctx: ParentComp, cm: boolean) => {
|
||||
if (cm) {
|
||||
text(0);
|
||||
elementStart(1, MyComp);
|
||||
elementStart(1, 'my-comp');
|
||||
elementEnd();
|
||||
}
|
||||
textBinding(0, interpolation1('', ctx.doCheckCount, ' - '));
|
||||
}
|
||||
},
|
||||
directiveDefs: () => [MyComp.ngComponentDef]
|
||||
});
|
||||
}
|
||||
|
||||
class Dir {
|
||||
constructor(public cdr: ChangeDetectorRef) {}
|
||||
|
||||
static ngDirectiveDef =
|
||||
defineDirective({type: Dir, factory: () => dir = new Dir(injectChangeDetectorRef())});
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: Dir,
|
||||
selector: [[['', 'dir', ''], null]],
|
||||
factory: () => dir = new Dir(injectChangeDetectorRef())
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -399,20 +387,13 @@ describe('change detection', () => {
|
|||
});
|
||||
|
||||
it('should check component view when called by directive on component node', () => {
|
||||
class MyApp {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
factory: () => new MyApp(),
|
||||
/** <my-comp dir></my-comp> */
|
||||
template: (ctx: MyApp, cm: boolean) => {
|
||||
if (cm) {
|
||||
elementStart(0, MyComp, ['dir', ''], [Dir]);
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
/** <my-comp dir></my-comp> */
|
||||
const MyApp = createComponent('my-app', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'my-comp', ['dir', '']);
|
||||
elementEnd();
|
||||
}
|
||||
}, [MyComp.ngComponentDef, Dir.ngDirectiveDef]);
|
||||
|
||||
const app = renderComponent(MyApp);
|
||||
expect(getRenderedText(app)).toEqual('Nancy');
|
||||
|
@ -423,32 +404,25 @@ describe('change detection', () => {
|
|||
});
|
||||
|
||||
it('should check host component when called by directive on element node', () => {
|
||||
class MyApp {
|
||||
name = 'Frank';
|
||||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
factory: () => new MyApp(),
|
||||
/**
|
||||
* {{ name }}
|
||||
* <div dir></div>
|
||||
*/
|
||||
template: (ctx: MyApp, cm: boolean) => {
|
||||
if (cm) {
|
||||
text(0);
|
||||
elementStart(1, 'div', ['dir', ''], [Dir]);
|
||||
elementEnd();
|
||||
}
|
||||
textBinding(1, bind(ctx.name));
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* {{ name }}
|
||||
* <div dir></div>
|
||||
*/
|
||||
const MyApp = createComponent('my-app', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
text(0);
|
||||
elementStart(1, 'div', ['dir', '']);
|
||||
elementEnd();
|
||||
}
|
||||
textBinding(1, bind(ctx.value));
|
||||
}, [Dir.ngDirectiveDef]);
|
||||
|
||||
const app = renderComponent(MyApp);
|
||||
app.value = 'Frank';
|
||||
tick(app);
|
||||
expect(getRenderedText(app)).toEqual('Frank');
|
||||
|
||||
app.name = 'Joe';
|
||||
app.value = 'Joe';
|
||||
dir !.cdr.detectChanges();
|
||||
expect(getRenderedText(app)).toEqual('Joe');
|
||||
});
|
||||
|
@ -462,7 +436,7 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: () => new MyApp(injectChangeDetectorRef()),
|
||||
/**
|
||||
* {{ name}}
|
||||
|
@ -480,14 +454,15 @@ describe('change detection', () => {
|
|||
{
|
||||
if (ctx.showing) {
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, 'div', ['dir', ''], [Dir]);
|
||||
elementStart(0, 'div', ['dir', '']);
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
embeddedViewEnd();
|
||||
}
|
||||
containerRefreshEnd();
|
||||
}
|
||||
},
|
||||
directiveDefs: [Dir.ngDirectiveDef]
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -512,7 +487,7 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: DetectChangesComp,
|
||||
tag: 'detect-changes-comp',
|
||||
selector: [[['detect-changes-comp'], null]],
|
||||
factory: () => new DetectChangesComp(injectChangeDetectorRef()),
|
||||
/** {{ value }} */
|
||||
template: (ctx: DetectChangesComp, cm: boolean) => {
|
||||
|
@ -541,7 +516,7 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: DetectChangesComp,
|
||||
tag: 'detect-changes-comp',
|
||||
selector: [[['detect-changes-comp'], null]],
|
||||
factory: () => new DetectChangesComp(injectChangeDetectorRef()),
|
||||
/** {{ doCheckCount }} */
|
||||
template: (ctx: DetectChangesComp, cm: boolean) => {
|
||||
|
@ -567,15 +542,16 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: () => new MyApp(injectChangeDetectorRef()),
|
||||
/** <detached-comp></detached-comp> */
|
||||
template: (ctx: MyApp, cm: boolean) => {
|
||||
if (cm) {
|
||||
elementStart(0, DetachedComp);
|
||||
elementStart(0, 'detached-comp');
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
},
|
||||
directiveDefs: () => [DetachedComp.ngComponentDef]
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -589,7 +565,7 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: DetachedComp,
|
||||
tag: 'detached-comp',
|
||||
selector: [[['detached-comp'], null]],
|
||||
factory: () => comp = new DetachedComp(injectChangeDetectorRef()),
|
||||
/** {{ value }} */
|
||||
template: (ctx: DetachedComp, cm: boolean) => {
|
||||
|
@ -685,7 +661,7 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: OnPushComp,
|
||||
tag: 'on-push-comp',
|
||||
selector: [[['on-push-comp'], null]],
|
||||
factory: () => onPushComp = new OnPushComp(injectChangeDetectorRef()),
|
||||
/** {{ value }} */
|
||||
template: (ctx: OnPushComp, cm: boolean) => {
|
||||
|
@ -699,25 +675,18 @@ describe('change detection', () => {
|
|||
});
|
||||
}
|
||||
|
||||
class OnPushApp {
|
||||
value = 'one';
|
||||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: OnPushApp,
|
||||
tag: 'on-push-app',
|
||||
factory: () => new OnPushApp(),
|
||||
/** <on-push-comp [value]="value"></on-push-comp> */
|
||||
template: (ctx: OnPushApp, cm: boolean) => {
|
||||
if (cm) {
|
||||
elementStart(0, OnPushComp);
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'value', bind(ctx.value));
|
||||
}
|
||||
});
|
||||
}
|
||||
/** <on-push-comp [value]="value"></on-push-comp> */
|
||||
const OnPushApp = createComponent('on-push-app', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'on-push-comp');
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'value', bind(ctx.value));
|
||||
}, [OnPushComp.ngComponentDef]);
|
||||
|
||||
const app = renderComponent(OnPushApp);
|
||||
app.value = 'one';
|
||||
tick(app);
|
||||
expect(getRenderedText(app)).toEqual('one');
|
||||
|
||||
onPushComp !.cdr.detach();
|
||||
|
@ -748,7 +717,7 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: OnPushComp,
|
||||
tag: 'on-push-comp',
|
||||
selector: [[['on-push-comp'], null]],
|
||||
factory: () => comp = new OnPushComp(injectChangeDetectorRef()),
|
||||
/** {{ value }} */
|
||||
template: (ctx: OnPushComp, cm: boolean) => {
|
||||
|
@ -766,7 +735,7 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: OnPushParent,
|
||||
tag: 'on-push-parent',
|
||||
selector: [[['on-push-parent'], null]],
|
||||
factory: () => new OnPushParent(),
|
||||
/**
|
||||
* {{ value }} -
|
||||
|
@ -775,11 +744,12 @@ describe('change detection', () => {
|
|||
template: (ctx: OnPushParent, cm: boolean) => {
|
||||
if (cm) {
|
||||
text(0);
|
||||
elementStart(1, OnPushComp);
|
||||
elementStart(1, 'on-push-comp');
|
||||
elementEnd();
|
||||
}
|
||||
textBinding(0, interpolation1('', ctx.value, ' - '));
|
||||
},
|
||||
directiveDefs: () => [OnPushComp.ngComponentDef],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
});
|
||||
}
|
||||
|
@ -832,7 +802,7 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: EmbeddedViewParent,
|
||||
tag: 'embedded-view-parent',
|
||||
selector: [[['embedded-view-parent'], null]],
|
||||
factory: () => new EmbeddedViewParent(),
|
||||
/**
|
||||
* {{ value }} -
|
||||
|
@ -850,7 +820,7 @@ describe('change detection', () => {
|
|||
{
|
||||
if (ctx.showing) {
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, OnPushComp);
|
||||
elementStart(0, 'on-push-comp');
|
||||
elementEnd();
|
||||
}
|
||||
embeddedViewEnd();
|
||||
|
@ -858,6 +828,7 @@ describe('change detection', () => {
|
|||
}
|
||||
containerRefreshEnd();
|
||||
},
|
||||
directiveDefs: () => [OnPushComp.ngComponentDef],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
});
|
||||
}
|
||||
|
@ -904,7 +875,7 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: NoChangesComp,
|
||||
tag: 'no-changes-comp',
|
||||
selector: [[['no-changes-comp'], null]],
|
||||
factory: () => comp = new NoChangesComp(injectChangeDetectorRef()),
|
||||
template: (ctx: NoChangesComp, cm: boolean) => {
|
||||
if (cm) {
|
||||
|
@ -922,7 +893,7 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: AppComp,
|
||||
tag: 'app-comp',
|
||||
selector: [[['app-comp'], null]],
|
||||
factory: () => new AppComp(injectChangeDetectorRef()),
|
||||
/**
|
||||
* {{ value }} -
|
||||
|
@ -931,11 +902,12 @@ describe('change detection', () => {
|
|||
template: (ctx: AppComp, cm: boolean) => {
|
||||
if (cm) {
|
||||
text(0);
|
||||
elementStart(1, NoChangesComp);
|
||||
elementStart(1, 'no-changes-comp');
|
||||
elementEnd();
|
||||
}
|
||||
textBinding(0, interpolation1('', ctx.value, ' - '));
|
||||
}
|
||||
},
|
||||
directiveDefs: () => [NoChangesComp.ngComponentDef]
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -981,7 +953,7 @@ describe('change detection', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: EmbeddedViewApp,
|
||||
tag: 'embedded-view-app',
|
||||
selector: [[['embedded-view-app'], null]],
|
||||
factory: () => new EmbeddedViewApp(injectChangeDetectorRef()),
|
||||
/**
|
||||
* % if (showing) {
|
||||
|
|
|
@ -23,14 +23,14 @@ describe('@angular/common integration', () => {
|
|||
static ngComponentDef = defineComponent({
|
||||
type: MyApp,
|
||||
factory: () => new MyApp(),
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
// <ul>
|
||||
// <li *ngFor="let item of items">{{item}}</li>
|
||||
// </ul>
|
||||
template: (myApp: MyApp, cm: boolean) => {
|
||||
if (cm) {
|
||||
elementStart(0, 'ul');
|
||||
{ container(1, [NgForOf], liTemplate); }
|
||||
{ container(1, liTemplate, undefined, ['ngForOf', '']); }
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(1, 'ngForOf', bind(myApp.items));
|
||||
|
@ -45,7 +45,8 @@ describe('@angular/common integration', () => {
|
|||
}
|
||||
textBinding(1, bind(row.$implicit));
|
||||
}
|
||||
}
|
||||
},
|
||||
directiveDefs: () => [NgForOf.ngDirectiveDef]
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -54,4 +55,4 @@ describe('@angular/common integration', () => {
|
|||
});
|
||||
// TODO: Test inheritance
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -16,6 +16,7 @@ export const NgForOf: DirectiveType<NgForOfDef<any>> = NgForOfDef as any;
|
|||
|
||||
NgForOf.ngDirectiveDef = defineDirective({
|
||||
type: NgForOfDef,
|
||||
selector: [[['', 'ngForOf', ''], null]],
|
||||
factory: () => new NgForOfDef(
|
||||
injectViewContainerRef(), injectTemplateRef(),
|
||||
directiveInject(IterableDiffers, InjectFlags.Default, defaultIterableDiffers)),
|
||||
|
|
|
@ -28,7 +28,7 @@ describe('components & directives', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: ChildComponent,
|
||||
tag: `child`,
|
||||
selector: [[['child'], null]],
|
||||
factory: () => new ChildComponent(),
|
||||
template: function(ctx: $ChildComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -47,6 +47,7 @@ describe('components & directives', () => {
|
|||
// NORMATIVE
|
||||
static ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: SomeDirective,
|
||||
selector: [[['', 'some-directive', ''], null]],
|
||||
factory: () => new SomeDirective(),
|
||||
});
|
||||
// /NORMATIVE
|
||||
|
@ -55,7 +56,6 @@ describe('components & directives', () => {
|
|||
// Important: keep arrays outside of function to not create new instances.
|
||||
// NORMATIVE
|
||||
const $e0_attrs$ = ['some-directive', ''];
|
||||
const $e0_dirs$ = [SomeDirective];
|
||||
// /NORMATIVE
|
||||
|
||||
@Component({selector: 'my-component', template: `<child some-directive></child>!`})
|
||||
|
@ -63,11 +63,11 @@ describe('components & directives', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: () => new MyComponent(),
|
||||
template: function(ctx: $MyComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, ChildComponent, $e0_attrs$, $e0_dirs$);
|
||||
$r3$.ɵE(0, 'child', $e0_attrs$);
|
||||
$r3$.ɵe();
|
||||
$r3$.ɵT(1, '!');
|
||||
}
|
||||
|
@ -76,6 +76,11 @@ describe('components & directives', () => {
|
|||
// /NORMATIVE
|
||||
}
|
||||
|
||||
// NON-NORMATIVE (done by defineNgModule)
|
||||
MyComponent.ngComponentDef.directiveDefs =
|
||||
[ChildComponent.ngComponentDef, SomeDirective.ngDirectiveDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
expect(renderComp(MyComponent)).toEqual('<child some-directive="">child-view</child>!');
|
||||
expect(log).toEqual(['ChildComponent', 'SomeDirective']);
|
||||
});
|
||||
|
@ -90,6 +95,7 @@ describe('components & directives', () => {
|
|||
// NORMATIVE
|
||||
static ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: HostBindingDir,
|
||||
selector: [[['', 'hostBindingDir', ''], null]],
|
||||
factory: function HostBindingDir_Factory() { return new HostBindingDir(); },
|
||||
hostBindings: function HostBindingDir_HostBindings(dirIndex: $number$, elIndex: $number$) {
|
||||
$r3$.ɵp(elIndex, 'id', $r3$.ɵb($r3$.ɵd<HostBindingDir>(dirIndex).dirId));
|
||||
|
@ -99,7 +105,6 @@ describe('components & directives', () => {
|
|||
}
|
||||
|
||||
const $e0_attrs$ = ['hostBindingDir', ''];
|
||||
const $e0_dirs$ = [HostBindingDir];
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
|
@ -110,17 +115,21 @@ describe('components & directives', () => {
|
|||
class MyApp {
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, 'div', $e0_attrs$, $e0_dirs$);
|
||||
$r3$.ɵE(0, 'div', $e0_attrs$);
|
||||
$r3$.ɵe();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// NON-NORMATIVE (done by defineNgModule)
|
||||
MyApp.ngComponentDef.directiveDefs = [HostBindingDir.ngDirectiveDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
expect(renderComp(MyApp)).toEqual(`<div hostbindingdir="" id="some id"></div>`);
|
||||
});
|
||||
|
||||
|
@ -134,6 +143,7 @@ describe('components & directives', () => {
|
|||
|
||||
// NORMATIVE
|
||||
static ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
selector: [[['', 'hostListenerDir', ''], null]],
|
||||
type: HostListenerDir,
|
||||
factory: function HostListenerDir_Factory() {
|
||||
const $dir$ = new HostListenerDir();
|
||||
|
@ -145,7 +155,6 @@ describe('components & directives', () => {
|
|||
}
|
||||
|
||||
const $e0_attrs$ = ['hostListenerDir', ''];
|
||||
const $e0_dirs$ = [HostListenerDir];
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
|
@ -156,11 +165,11 @@ describe('components & directives', () => {
|
|||
class MyApp {
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, 'button', $e0_attrs$, $e0_dirs$);
|
||||
$r3$.ɵE(0, 'button', $e0_attrs$);
|
||||
$r3$.ɵT(1, 'Click');
|
||||
$r3$.ɵe();
|
||||
}
|
||||
|
@ -168,6 +177,10 @@ describe('components & directives', () => {
|
|||
});
|
||||
}
|
||||
|
||||
// NON-NORMATIVE (done by defineNgModule)
|
||||
MyApp.ngComponentDef.directiveDefs = [HostListenerDir.ngDirectiveDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
expect(renderComp(MyApp)).toEqual(`<button hostlistenerdir="">Click</button>`);
|
||||
});
|
||||
|
||||
|
@ -179,6 +192,7 @@ describe('components & directives', () => {
|
|||
class HostAttributeDir {
|
||||
// NORMATIVE
|
||||
static ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
selector: [[['', 'hostAttributeDir', ''], null]],
|
||||
type: HostAttributeDir,
|
||||
factory: function HostAttributeDir_Factory() { return new HostAttributeDir(); },
|
||||
attributes: ['role', 'listbox']
|
||||
|
@ -187,7 +201,6 @@ describe('components & directives', () => {
|
|||
}
|
||||
|
||||
const $e0_attrs$ = ['hostAttributeDir', ''];
|
||||
const $e0_dirs$ = [HostAttributeDir];
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
|
@ -198,17 +211,21 @@ describe('components & directives', () => {
|
|||
class MyApp {
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, 'div', $e0_attrs$, $e0_dirs$);
|
||||
$r3$.ɵE(0, 'div', $e0_attrs$);
|
||||
$r3$.ɵe();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// NON-NORMATIVE (done by defineNgModule)
|
||||
MyApp.ngComponentDef.directiveDefs = [HostAttributeDir.ngDirectiveDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
expect(renderComp(MyApp)).toEqual(`<div hostattributedir="" role="listbox"></div>`);
|
||||
});
|
||||
|
||||
|
@ -222,6 +239,7 @@ describe('components & directives', () => {
|
|||
// NORMATIVE
|
||||
static ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: HostBindingDir,
|
||||
selector: [[['', 'hostBindingDir', ''], null]],
|
||||
factory: function HostBindingDir_Factory() { return new HostBindingDir(); },
|
||||
hostBindings: function HostBindingDir_HostBindings(dirIndex: $number$, elIndex: $number$) {
|
||||
$r3$.ɵa(elIndex, 'aria-label', $r3$.ɵb($r3$.ɵd<HostBindingDir>(dirIndex).label));
|
||||
|
@ -231,7 +249,6 @@ describe('components & directives', () => {
|
|||
}
|
||||
|
||||
const $e0_attrs$ = ['hostBindingDir', ''];
|
||||
const $e0_dirs$ = [HostBindingDir];
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
|
@ -242,17 +259,21 @@ describe('components & directives', () => {
|
|||
class MyApp {
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, 'div', $e0_attrs$, $e0_dirs$);
|
||||
$r3$.ɵE(0, 'div', $e0_attrs$);
|
||||
$r3$.ɵe();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// NON-NORMATIVE (done by defineNgModule)
|
||||
MyApp.ngComponentDef.directiveDefs = [HostBindingDir.ngDirectiveDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
expect(renderComp(MyApp)).toEqual(`<div aria-label="some label" hostbindingdir=""></div>`);
|
||||
});
|
||||
|
||||
|
@ -273,7 +294,7 @@ describe('components & directives', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComp,
|
||||
tag: 'my-comp',
|
||||
selector: [[['my-comp'], null]],
|
||||
factory: function MyComp_Factory() { return new MyComp(); },
|
||||
template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -298,11 +319,11 @@ describe('components & directives', () => {
|
|||
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, MyComp);
|
||||
$r3$.ɵE(0, 'my-comp');
|
||||
$r3$.ɵe();
|
||||
}
|
||||
$r3$.ɵp(0, 'name', $r3$.ɵb(ctx.name));
|
||||
|
@ -310,6 +331,10 @@ describe('components & directives', () => {
|
|||
});
|
||||
}
|
||||
|
||||
// NON-NORMATIVE (done by defineNgModule)
|
||||
MyApp.ngComponentDef.directiveDefs = [MyComp.ngComponentDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
expect(renderComp(MyApp)).toEqual(`<my-comp>some name</my-comp>`);
|
||||
});
|
||||
|
||||
|
@ -325,6 +350,7 @@ describe('components & directives', () => {
|
|||
// NORMATIVE
|
||||
static ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: IfDirective,
|
||||
selector: [[['', 'if', ''], null]],
|
||||
factory: () => new IfDirective($r3$.ɵinjectTemplateRef()),
|
||||
});
|
||||
// /NORMATIVE
|
||||
|
@ -333,7 +359,6 @@ describe('components & directives', () => {
|
|||
// Important: keep arrays outside of function to not create new instances.
|
||||
// NORMATIVE
|
||||
const $e0_locals$ = ['foo', ''];
|
||||
const $c1_dirs$ = [IfDirective];
|
||||
// /NORMATIVE
|
||||
|
||||
@Component(
|
||||
|
@ -343,12 +368,12 @@ describe('components & directives', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: () => new MyComponent(),
|
||||
template: function(ctx: $MyComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, 'ul', null, null, $e0_locals$);
|
||||
$r3$.ɵC(2, $c1_dirs$, C1);
|
||||
$r3$.ɵE(0, 'ul', null, $e0_locals$);
|
||||
$r3$.ɵC(2, C1, '', ['if', '']);
|
||||
$r3$.ɵe();
|
||||
}
|
||||
let $foo$ = $r3$.ɵld<any>(1);
|
||||
|
@ -386,7 +411,7 @@ describe('components & directives', () => {
|
|||
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyArrayComp,
|
||||
tag: 'my-array-comp',
|
||||
selector: [[['my-array-comp'], null]],
|
||||
factory: function MyArrayComp_Factory() { return new MyArrayComp(); },
|
||||
template: function MyArrayComp_Template(ctx: $MyArrayComp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -415,11 +440,11 @@ describe('components & directives', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, MyArrayComp);
|
||||
$r3$.ɵE(0, 'my-array-comp');
|
||||
$r3$.ɵe();
|
||||
}
|
||||
$r3$.ɵp(0, 'names', cm ? $e0_arr$ : $r3$.ɵNC);
|
||||
|
@ -428,6 +453,10 @@ describe('components & directives', () => {
|
|||
// /NORMATIVE
|
||||
}
|
||||
|
||||
// NON-NORMATIVE (done by defineNgModule)
|
||||
MyApp.ngComponentDef.directiveDefs = [MyArrayComp.ngComponentDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
expect(renderComp(MyApp)).toEqual(`<my-array-comp>Nancy Bess</my-array-comp>`);
|
||||
});
|
||||
|
||||
|
@ -453,11 +482,11 @@ describe('components & directives', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, MyArrayComp);
|
||||
$r3$.ɵE(0, 'my-array-comp');
|
||||
$r3$.ɵe();
|
||||
}
|
||||
$r3$.ɵp(0, 'names', $r3$.ɵb(ctx.someFn($r3$.ɵf0($e0_ff$))));
|
||||
|
@ -466,6 +495,10 @@ describe('components & directives', () => {
|
|||
// /NORMATIVE
|
||||
}
|
||||
|
||||
// NON-NORMATIVE (done by defineNgModule)
|
||||
MyApp.ngComponentDef.directiveDefs = [MyArrayComp.ngComponentDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
expect(renderComp(MyApp)).toEqual(`<my-array-comp>NANCY Bess</my-array-comp>`);
|
||||
});
|
||||
|
||||
|
@ -479,7 +512,7 @@ describe('components & directives', () => {
|
|||
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComp,
|
||||
tag: 'my-comp',
|
||||
selector: [[['my-comp'], null]],
|
||||
factory: function MyComp_Factory() { return new MyComp(); },
|
||||
template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -505,11 +538,11 @@ describe('components & directives', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, MyComp);
|
||||
$r3$.ɵE(0, 'my-comp');
|
||||
$r3$.ɵe();
|
||||
}
|
||||
$r3$.ɵp(0, 'num', $r3$.ɵb($r3$.ɵf0($e0_ff$).length + 1));
|
||||
|
@ -518,6 +551,10 @@ describe('components & directives', () => {
|
|||
// /NORMATIVE
|
||||
}
|
||||
|
||||
// NON-NORMATIVE (done by defineNgModule)
|
||||
MyApp.ngComponentDef.directiveDefs = [MyComp.ngComponentDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
expect(renderComp(MyApp)).toEqual(`<my-comp>3</my-comp>`);
|
||||
});
|
||||
|
||||
|
@ -541,11 +578,11 @@ describe('components & directives', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, MyArrayComp);
|
||||
$r3$.ɵE(0, 'my-array-comp');
|
||||
$r3$.ɵe();
|
||||
}
|
||||
$r3$.ɵp(0, 'names', $r3$.ɵb($r3$.ɵf1($e0_ff$, ctx.customName)));
|
||||
|
@ -554,6 +591,10 @@ describe('components & directives', () => {
|
|||
// /NORMATIVE
|
||||
}
|
||||
|
||||
// NON-NORMATIVE (done by defineNgModule)
|
||||
MyApp.ngComponentDef.directiveDefs = [MyArrayComp.ngComponentDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
expect(renderComp(MyApp)).toEqual(`<my-array-comp>Nancy Bess</my-array-comp>`);
|
||||
});
|
||||
|
||||
|
@ -581,7 +622,7 @@ describe('components & directives', () => {
|
|||
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComp,
|
||||
tag: 'my-comp',
|
||||
selector: [[['my-comp'], null]],
|
||||
factory: function MyComp_Factory() { return new MyComp(); },
|
||||
template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -642,11 +683,11 @@ describe('components & directives', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(c: MyApp, cm: boolean) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, MyComp);
|
||||
$r3$.ɵE(0, 'my-comp');
|
||||
$r3$.ɵe();
|
||||
}
|
||||
$r3$.ɵp(
|
||||
|
@ -657,6 +698,10 @@ describe('components & directives', () => {
|
|||
// /NORMATIVE
|
||||
}
|
||||
|
||||
// NON-NORMATIVE (done by defineNgModule)
|
||||
MyApp.ngComponentDef.directiveDefs = [MyComp.ngComponentDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
expect(renderComp(MyApp)).toEqual(`<my-comp>start-abcde-middle-fghi-end</my-comp>`);
|
||||
});
|
||||
|
||||
|
@ -676,7 +721,7 @@ describe('components & directives', () => {
|
|||
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: ObjectComp,
|
||||
tag: 'object-comp',
|
||||
selector: [[['object-comp'], null]],
|
||||
factory: function ObjectComp_Factory() { return new ObjectComp(); },
|
||||
template: function ObjectComp_Template(ctx: $ObjectComp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -710,11 +755,11 @@ describe('components & directives', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, ObjectComp);
|
||||
$r3$.ɵE(0, 'object-comp');
|
||||
$r3$.ɵe();
|
||||
}
|
||||
$r3$.ɵp(0, 'config', $r3$.ɵb($r3$.ɵf1($e0_ff$, ctx.name)));
|
||||
|
@ -723,6 +768,10 @@ describe('components & directives', () => {
|
|||
// /NORMATIVE
|
||||
}
|
||||
|
||||
// NON-NORMATIVE (done by defineNgModule)
|
||||
MyApp.ngComponentDef.directiveDefs = [ObjectComp.ngComponentDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
expect(renderComp(MyApp)).toEqual(`<object-comp><p>500</p><p>slide</p></object-comp>`);
|
||||
});
|
||||
|
||||
|
@ -743,7 +792,7 @@ describe('components & directives', () => {
|
|||
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: NestedComp,
|
||||
tag: 'nested-comp',
|
||||
selector: [[['nested-comp'], null]],
|
||||
factory: function NestedComp_Factory() { return new NestedComp(); },
|
||||
template: function NestedComp_Template(ctx: $NestedComp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -786,11 +835,11 @@ describe('components & directives', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, NestedComp);
|
||||
$r3$.ɵE(0, 'nested-comp');
|
||||
$r3$.ɵe();
|
||||
}
|
||||
$r3$.ɵp(
|
||||
|
@ -802,6 +851,10 @@ describe('components & directives', () => {
|
|||
// /NORMATIVE
|
||||
}
|
||||
|
||||
// NON-NORMATIVE (done by defineNgModule)
|
||||
MyApp.ngComponentDef.directiveDefs = [NestedComp.ngComponentDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
expect(renderComp(MyApp))
|
||||
.toEqual(`<nested-comp><p>slide</p><p>0</p><p>100</p></nested-comp>`);
|
||||
});
|
||||
|
|
|
@ -24,7 +24,7 @@ describe('content projection', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: SimpleComponent,
|
||||
tag: 'simple',
|
||||
selector: [[['simple'], null]],
|
||||
factory: () => new SimpleComponent(),
|
||||
template: function(ctx: $SimpleComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -54,7 +54,7 @@ describe('content projection', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: ComplexComponent,
|
||||
tag: 'complex',
|
||||
selector: [[['complex'], null]],
|
||||
factory: () => new ComplexComponent(),
|
||||
template: function(ctx: $ComplexComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -79,15 +79,16 @@ describe('content projection', () => {
|
|||
class MyApp {
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: () => new MyApp(),
|
||||
template: function(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, SimpleComponent);
|
||||
$r3$.ɵE(0, 'simple');
|
||||
$r3$.ɵT(1, 'content');
|
||||
$r3$.ɵe();
|
||||
}
|
||||
}
|
||||
},
|
||||
directiveDefs: () => [SimpleComponent.ngComponentDef]
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -32,7 +32,7 @@ describe('elements', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: () => new MyComponent(),
|
||||
template: function(ctx: $MyComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -69,7 +69,7 @@ describe('elements', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: ListenerComp,
|
||||
tag: 'listener-comp',
|
||||
selector: [[['listener-comp'], null]],
|
||||
factory: function ListenerComp_Factory() { return new ListenerComp(); },
|
||||
template: function ListenerComp_Template(ctx: $ListenerComp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -101,7 +101,7 @@ describe('elements', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: function MyComponent_Factory() { return new MyComponent(); },
|
||||
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -131,7 +131,7 @@ describe('elements', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: function MyComponent_Factory() { return new MyComponent(); },
|
||||
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -161,7 +161,7 @@ describe('elements', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: function MyComponent_Factory() { return new MyComponent(); },
|
||||
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -195,7 +195,7 @@ describe('elements', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: function MyComponent_Factory() { return new MyComponent(); },
|
||||
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -243,7 +243,7 @@ describe('elements', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: function MyComponent_Factory() { return new MyComponent(); },
|
||||
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -277,7 +277,7 @@ describe('elements', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: StyleComponent,
|
||||
tag: 'style-comp',
|
||||
selector: [[['style-comp'], null]],
|
||||
factory: function StyleComponent_Factory() { return new StyleComponent(); },
|
||||
template: function StyleComponent_Template(ctx: $StyleComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
|
|
@ -30,7 +30,7 @@ describe('injection', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComp,
|
||||
tag: 'my-comp',
|
||||
selector: [[['my-comp'], null]],
|
||||
factory: function MyComp_Factory() {
|
||||
return new MyComp($r3$.ɵinjectChangeDetectorRef());
|
||||
},
|
||||
|
@ -47,18 +47,20 @@ describe('injection', () => {
|
|||
class MyApp {
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
/** <my-comp></my-comp> */
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, MyComp);
|
||||
$r3$.ɵE(0, 'my-comp');
|
||||
$r3$.ɵe();
|
||||
}
|
||||
}
|
||||
},
|
||||
directiveDefs: () => [MyComp.ngComponentDef]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const app = renderComponent(MyApp);
|
||||
// ChangeDetectorRef is the token, ViewRef is historically the constructor
|
||||
expect(toHtml(app)).toEqual('<my-comp>ViewRef</my-comp>');
|
||||
|
@ -75,7 +77,7 @@ describe('injection', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComp,
|
||||
tag: 'my-comp',
|
||||
selector: [[['my-comp'], null]],
|
||||
factory: function MyComp_Factory() { return new MyComp($r3$.ɵinjectAttribute('title')); },
|
||||
template: function MyComp_Template(ctx: $MyComp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -90,15 +92,16 @@ describe('injection', () => {
|
|||
class MyApp {
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
/** <my-comp></my-comp> */
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, MyComp, e0_attrs);
|
||||
$r3$.ɵE(0, 'my-comp', e0_attrs);
|
||||
$r3$.ɵe();
|
||||
}
|
||||
}
|
||||
},
|
||||
directiveDefs: () => [MyComp.ngComponentDef]
|
||||
});
|
||||
}
|
||||
const e0_attrs = ['title', 'WORKS'];
|
||||
|
@ -139,7 +142,7 @@ describe('injection', () => {
|
|||
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() {
|
||||
return new MyApp(
|
||||
$r3$.ɵdirectiveInject(ServiceA), $r3$.ɵdirectiveInject(ServiceB), inject(INJECTOR));
|
||||
|
|
|
@ -41,7 +41,7 @@ describe('lifecycle hooks', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: LifecycleComp,
|
||||
tag: 'lifecycle-comp',
|
||||
selector: [[['lifecycle-comp'], null]],
|
||||
factory: function LifecycleComp_Factory() { return new LifecycleComp(); },
|
||||
template: function LifecycleComp_Template(ctx: $LifecycleComp$, cm: $boolean$) {},
|
||||
inputs: {nameMin: 'name'},
|
||||
|
@ -64,13 +64,13 @@ describe('lifecycle hooks', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: SimpleLayout,
|
||||
tag: 'simple-layout',
|
||||
selector: [[['simple-layout'], null]],
|
||||
factory: function SimpleLayout_Factory() { return simpleLayout = new SimpleLayout(); },
|
||||
template: function SimpleLayout_Template(ctx: $SimpleLayout$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, LifecycleComp);
|
||||
$r3$.ɵE(0, 'lifecycle-comp');
|
||||
$r3$.ɵe();
|
||||
$r3$.ɵE(1, LifecycleComp);
|
||||
$r3$.ɵE(1, 'lifecycle-comp');
|
||||
$r3$.ɵe();
|
||||
}
|
||||
$r3$.ɵp(0, 'name', $r3$.ɵb(ctx.name1));
|
||||
|
@ -80,6 +80,10 @@ describe('lifecycle hooks', () => {
|
|||
// /NORMATIVE
|
||||
}
|
||||
|
||||
// NON-NORMATIVE
|
||||
SimpleLayout.ngComponentDef.directiveDefs = [LifecycleComp.ngComponentDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
it('should gen hooks with a few simple components', () => {
|
||||
expect(toHtml(renderComponent(SimpleLayout)))
|
||||
.toEqual(`<lifecycle-comp></lifecycle-comp><lifecycle-comp></lifecycle-comp>`);
|
||||
|
|
|
@ -23,11 +23,11 @@ describe('local references', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: () => new MyComponent,
|
||||
template: function(ctx: $MyComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, 'input', null, null, ['user', '']);
|
||||
$r3$.ɵE(0, 'input', null, ['user', '']);
|
||||
$r3$.ɵe();
|
||||
$r3$.ɵT(2);
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ describe('pipes', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
@ -133,17 +133,13 @@ describe('pipes', () => {
|
|||
// NORMATIVE
|
||||
static ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: OneTimeIf,
|
||||
selector: [[['', 'oneTimeIf', ''], null]],
|
||||
factory: () => new OneTimeIf($r3$.ɵinjectViewContainerRef(), $r3$.ɵinjectTemplateRef()),
|
||||
inputs: {oneTimeIf: 'oneTimeIf'}
|
||||
});
|
||||
// /NORMATIVE
|
||||
}
|
||||
|
||||
// Important: keep arrays outside of function to not create new instances.
|
||||
// NORMATIVE
|
||||
const $c1_dirs$ = [OneTimeIf];
|
||||
// /NORMATIVE
|
||||
|
||||
@Component({
|
||||
template: `{{name | myPurePipe:size}}{{name | myPurePipe:size}}
|
||||
<div *oneTimeIf="more">{{name | myPurePipe:size}}</div>`
|
||||
|
@ -156,7 +152,7 @@ describe('pipes', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
let $pi$: $MyPurePipe$;
|
||||
|
@ -165,7 +161,7 @@ describe('pipes', () => {
|
|||
$pi$ = $r3$.ɵPp(1, $MyPurePipe_ngPipeDef$);
|
||||
$r3$.ɵT(2);
|
||||
$r3$.ɵPp(3, $MyPurePipe_ngPipeDef$, $pi$);
|
||||
$r3$.ɵC(4, $c1_dirs$, C4);
|
||||
$r3$.ɵC(4, C4, '', ['oneTimeIf', '']);
|
||||
}
|
||||
$r3$.ɵt(0, $r3$.ɵi1('', $r3$.ɵpb2(1, ctx.name, ctx.size), ''));
|
||||
$r3$.ɵt(2, $r3$.ɵi1('', $r3$.ɵpb2(3, ctx.name, ctx.size), ''));
|
||||
|
@ -187,6 +183,10 @@ describe('pipes', () => {
|
|||
// /NORMATIVE
|
||||
}
|
||||
|
||||
// NON-NORMATIVE
|
||||
MyApp.ngComponentDef.directiveDefs = [OneTimeIf.ngDirectiveDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
let myApp: MyApp = renderComponent(MyApp);
|
||||
expect(toHtml(containerEl)).toEqual('WorldWorld<div>World</div>');
|
||||
expect(myPurePipeTransformCalls).toEqual(3);
|
||||
|
|
|
@ -22,6 +22,7 @@ describe('queries', () => {
|
|||
class SomeDirective {
|
||||
static ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: SomeDirective,
|
||||
selector: [[['', 'someDir', ''], null]],
|
||||
factory: function SomeDirective_Factory() { return someDir = new SomeDirective(); },
|
||||
features: [$r3$.ɵPublicFeature]
|
||||
});
|
||||
|
@ -32,7 +33,6 @@ describe('queries', () => {
|
|||
|
||||
// NORMATIVE
|
||||
const $e1_attrs$ = ['someDir', ''];
|
||||
const $e1_dirs$ = [SomeDirective];
|
||||
// /NORMATIVE
|
||||
|
||||
@Component({
|
||||
|
@ -48,14 +48,14 @@ describe('queries', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: ViewQueryComponent,
|
||||
tag: 'view-query-component',
|
||||
selector: [[['view-query-component'], null]],
|
||||
factory: function ViewQueryComponent_Factory() { return new ViewQueryComponent(); },
|
||||
template: function ViewQueryComponent_Template(ctx: $ViewQueryComponent$, cm: $boolean$) {
|
||||
let $tmp$: any;
|
||||
if (cm) {
|
||||
$r3$.ɵQ(0, SomeDirective, false);
|
||||
$r3$.ɵQ(1, SomeDirective, false);
|
||||
$r3$.ɵE(2, 'div', $e1_attrs$, $e1_dirs$);
|
||||
$r3$.ɵE(2, 'div', $e1_attrs$);
|
||||
$r3$.ɵe();
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,9 @@ describe('queries', () => {
|
|||
// /NORMATIVE
|
||||
}
|
||||
|
||||
// NON-NORMATIVE
|
||||
ViewQueryComponent.ngComponentDef.directiveDefs = [SomeDirective.ngDirectiveDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
const viewQueryComp = renderComponent(ViewQueryComponent);
|
||||
expect(viewQueryComp.someDir).toEqual(someDir);
|
||||
|
@ -92,7 +95,7 @@ describe('queries', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: ContentQueryComponent,
|
||||
tag: 'content-query-component',
|
||||
selector: [[['content-query-component'], null]],
|
||||
factory: function ContentQueryComponent_Factory() {
|
||||
return [
|
||||
new ContentQueryComponent(), $r3$.ɵQ(null, SomeDirective, false),
|
||||
|
@ -120,7 +123,6 @@ describe('queries', () => {
|
|||
}
|
||||
|
||||
const $e2_attrs$ = ['someDir', ''];
|
||||
const $e2_dirs$ = [SomeDirective];
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
|
@ -134,13 +136,13 @@ describe('queries', () => {
|
|||
// NON-NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: function MyApp_Factory() { return new MyApp(); },
|
||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, ContentQueryComponent);
|
||||
$r3$.ɵE(0, 'content-query-component');
|
||||
contentQueryComp = $r3$.ɵd<any[]>(0)[0];
|
||||
$r3$.ɵE(1, 'div', $e2_attrs$, $e2_dirs$);
|
||||
$r3$.ɵE(1, 'div', $e2_attrs$);
|
||||
$r3$.ɵe();
|
||||
$r3$.ɵe();
|
||||
}
|
||||
|
@ -149,6 +151,10 @@ describe('queries', () => {
|
|||
// /NON-NORMATIVE
|
||||
}
|
||||
|
||||
// NON-NORMATIVE
|
||||
MyApp.ngComponentDef.directiveDefs =
|
||||
[ContentQueryComponent.ngComponentDef, SomeDirective.ngDirectiveDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
expect(toHtml(renderComponent(MyApp)))
|
||||
.toEqual(
|
||||
|
|
|
@ -38,7 +38,7 @@ describe('compiler sanitization', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: function MyComponent_Factory() { return new MyComponent(); },
|
||||
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
|
|
|
@ -58,7 +58,7 @@ class ToDoAppComponent {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = r3.defineComponent({
|
||||
type: ToDoAppComponent,
|
||||
tag: 'todo-app',
|
||||
selector: [[['todo-app'], null]],
|
||||
factory: function ToDoAppComponent_Factory() {
|
||||
return new ToDoAppComponent(r3.directiveInject(AppState));
|
||||
},
|
||||
|
@ -67,7 +67,7 @@ class ToDoAppComponent {
|
|||
const ToDoAppComponent_NgForOf_Template = function ToDoAppComponent_NgForOf_Template(
|
||||
ctx1: NgForOfContext<ToDo>, cm: boolean) {
|
||||
if (cm) {
|
||||
r3.E(0, ToDoItemComponent);
|
||||
r3.E(0, 'todo');
|
||||
r3.L('archive', ctx.onArchive.bind(ctx));
|
||||
r3.e();
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ class ToDoAppComponent {
|
|||
r3.T(1, 'ToDo Application');
|
||||
r3.e();
|
||||
r3.E(2, 'div');
|
||||
r3.C(3, c3_directives, ToDoAppComponent_NgForOf_Template);
|
||||
r3.C(3, ToDoAppComponent_NgForOf_Template, '', ['ngForOf', '']);
|
||||
r3.e();
|
||||
r3.E(4, 'span');
|
||||
r3.T(5);
|
||||
|
@ -89,9 +89,10 @@ class ToDoAppComponent {
|
|||
// /NORMATIVE
|
||||
}
|
||||
|
||||
// NORMATIVE
|
||||
const c3_directives = [NgForOf as r3.DirectiveType<NgForOf<ToDo>>];
|
||||
// /NORMATIVE
|
||||
// NON-NORMATIVE
|
||||
ToDoAppComponent.ngComponentDef.directiveDefs = () =>
|
||||
[ToDoItemComponent.ngComponentDef, (NgForOf as r3.DirectiveType<NgForOf<any>>).ngDirectiveDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
@Component({
|
||||
selector: 'todo',
|
||||
|
@ -122,7 +123,7 @@ class ToDoItemComponent {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = r3.defineComponent({
|
||||
type: ToDoItemComponent,
|
||||
tag: 'todo',
|
||||
selector: [[['todo'], null]],
|
||||
factory: function ToDoItemComponent_Factory() { return new ToDoItemComponent(); },
|
||||
template: function ToDoItemComponent_Template(ctx: ToDoItemComponent, cm: boolean) {
|
||||
if (cm) {
|
||||
|
|
|
@ -63,6 +63,7 @@ describe('template variables', () => {
|
|||
// NORMATIVE
|
||||
static ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: ForOfDirective,
|
||||
selector: [[['', 'forOf', ''], null]],
|
||||
factory: function ForOfDirective_Factory() {
|
||||
return new ForOfDirective($r3$.ɵinjectViewContainerRef(), $r3$.ɵinjectTemplateRef());
|
||||
},
|
||||
|
@ -80,10 +81,6 @@ describe('template variables', () => {
|
|||
name: string;
|
||||
}
|
||||
|
||||
// NORMATIVE
|
||||
const $c1_dirs$ = [ForOfDirective];
|
||||
// /NORMATIVE
|
||||
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: `<ul><li *for="let item of items">{{item.name}}</li></ul>`
|
||||
|
@ -94,12 +91,12 @@ describe('template variables', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: function MyComponent_Factory() { return new MyComponent(); },
|
||||
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, 'ul');
|
||||
$r3$.ɵC(1, $c1_dirs$, MyComponent_ForOfDirective_Template_1);
|
||||
$r3$.ɵC(1, MyComponent_ForOfDirective_Template_1, '', ['forOf', '']);
|
||||
$r3$.ɵe();
|
||||
}
|
||||
$r3$.ɵp(1, 'forOf', $r3$.ɵb(ctx.items));
|
||||
|
@ -120,6 +117,10 @@ describe('template variables', () => {
|
|||
// /NORMATIVE
|
||||
}
|
||||
|
||||
// NON-NORMATIVE
|
||||
MyComponent.ngComponentDef.directiveDefs = [ForOfDirective.ngDirectiveDef];
|
||||
// /NON-NORMATIVE
|
||||
|
||||
// TODO(chuckj): update when the changes to enable ngForOf lands.
|
||||
expect(toHtml(renderComponent(MyComponent))).toEqual('<ul></ul>');
|
||||
});
|
||||
|
@ -135,10 +136,6 @@ describe('template variables', () => {
|
|||
infos: Info[];
|
||||
}
|
||||
|
||||
// NORMATIVE
|
||||
const $c1_dirs$ = [ForOfDirective];
|
||||
// /NORMATIVE
|
||||
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: `
|
||||
|
@ -162,12 +159,12 @@ describe('template variables', () => {
|
|||
// NORMATIVE
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'my-component',
|
||||
selector: [[['my-component'], null]],
|
||||
factory: function MyComponent_Factory() { return new MyComponent(); },
|
||||
template: function MyComponent_Template(ctx: $MyComponent$, cm: $boolean$) {
|
||||
if (cm) {
|
||||
$r3$.ɵE(0, 'ul');
|
||||
$r3$.ɵC(1, $c1_dirs$, MyComponent_ForOfDirective_Template_1);
|
||||
$r3$.ɵC(1, MyComponent_ForOfDirective_Template_1, '', ['forOf', '']);
|
||||
$r3$.ɵe();
|
||||
}
|
||||
$r3$.ɵp(1, 'forOf', $r3$.ɵb(ctx.items));
|
||||
|
@ -181,7 +178,7 @@ describe('template variables', () => {
|
|||
$r3$.ɵT(2);
|
||||
$r3$.ɵe();
|
||||
$r3$.ɵE(3, 'ul');
|
||||
$r3$.ɵC(4, $c1_dirs$, MyComponent_ForOfDirective_ForOfDirective_Template_3);
|
||||
$r3$.ɵC(4, MyComponent_ForOfDirective_ForOfDirective_Template_3, '', ['forOf', '']);
|
||||
$r3$.ɵe();
|
||||
$r3$.ɵe();
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ describe('component', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: CounterComponent,
|
||||
tag: 'counter',
|
||||
selector: [[['counter'], null]],
|
||||
template: function(ctx: CounterComponent, cm: boolean) {
|
||||
if (cm) {
|
||||
text(0);
|
||||
|
@ -87,7 +87,7 @@ describe('component with a container', () => {
|
|||
items: string[];
|
||||
static ngComponentDef = defineComponent({
|
||||
type: WrapperComponent,
|
||||
tag: 'wrapper',
|
||||
selector: [[['wrapper'], null]],
|
||||
template: function ChildComponentTemplate(ctx: {items: string[]}, cm: boolean) {
|
||||
if (cm) {
|
||||
container(0);
|
||||
|
@ -107,18 +107,20 @@ describe('component with a container', () => {
|
|||
|
||||
function template(ctx: {items: string[]}, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, WrapperComponent);
|
||||
elementStart(0, 'wrapper');
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'items', bind(ctx.items));
|
||||
}
|
||||
|
||||
const defs = [WrapperComponent.ngComponentDef];
|
||||
|
||||
it('should re-render on input change', () => {
|
||||
const ctx: {items: string[]} = {items: ['a']};
|
||||
expect(renderToHtml(template, ctx)).toEqual('<wrapper>a</wrapper>');
|
||||
expect(renderToHtml(template, ctx, defs)).toEqual('<wrapper>a</wrapper>');
|
||||
|
||||
ctx.items = [...ctx.items, 'b'];
|
||||
expect(renderToHtml(template, ctx)).toEqual('<wrapper>ab</wrapper>');
|
||||
expect(renderToHtml(template, ctx, defs)).toEqual('<wrapper>ab</wrapper>');
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -129,38 +131,40 @@ describe('encapsulation', () => {
|
|||
class WrapperComponent {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: WrapperComponent,
|
||||
tag: 'wrapper',
|
||||
selector: [[['wrapper'], null]],
|
||||
template: function(ctx: WrapperComponent, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, EncapsulatedComponent);
|
||||
elementStart(0, 'encapsulated');
|
||||
elementEnd();
|
||||
}
|
||||
},
|
||||
factory: () => new WrapperComponent,
|
||||
directiveDefs: () => [EncapsulatedComponent.ngComponentDef]
|
||||
});
|
||||
}
|
||||
|
||||
class EncapsulatedComponent {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: EncapsulatedComponent,
|
||||
tag: 'encapsulated',
|
||||
selector: [[['encapsulated'], null]],
|
||||
template: function(ctx: EncapsulatedComponent, cm: boolean) {
|
||||
if (cm) {
|
||||
text(0, 'foo');
|
||||
elementStart(1, LeafComponent);
|
||||
elementStart(1, 'leaf');
|
||||
elementEnd();
|
||||
}
|
||||
},
|
||||
factory: () => new EncapsulatedComponent,
|
||||
rendererType:
|
||||
createRendererType2({encapsulation: ViewEncapsulation.Emulated, styles: [], data: {}}),
|
||||
directiveDefs: () => [LeafComponent.ngComponentDef]
|
||||
});
|
||||
}
|
||||
|
||||
class LeafComponent {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: LeafComponent,
|
||||
tag: 'leaf',
|
||||
selector: [[['leaf'], null]],
|
||||
template: function(ctx: LeafComponent, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'span');
|
||||
|
@ -190,23 +194,24 @@ describe('encapsulation', () => {
|
|||
class WrapperComponentWith {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: WrapperComponentWith,
|
||||
tag: 'wrapper',
|
||||
selector: [[['wrapper'], null]],
|
||||
template: function(ctx: WrapperComponentWith, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, LeafComponentwith);
|
||||
elementStart(0, 'leaf');
|
||||
elementEnd();
|
||||
}
|
||||
},
|
||||
factory: () => new WrapperComponentWith,
|
||||
rendererType:
|
||||
createRendererType2({encapsulation: ViewEncapsulation.Emulated, styles: [], data: {}}),
|
||||
directiveDefs: () => [LeafComponentwith.ngComponentDef]
|
||||
});
|
||||
}
|
||||
|
||||
class LeafComponentwith {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: LeafComponentwith,
|
||||
tag: 'leaf',
|
||||
selector: [[['leaf'], null]],
|
||||
template: function(ctx: LeafComponentwith, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'span');
|
||||
|
@ -245,7 +250,7 @@ describe('recursive components', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: TreeComponent,
|
||||
tag: 'tree-comp',
|
||||
selector: [[['tree-comp'], null]],
|
||||
factory: () => new TreeComponent(),
|
||||
template: (ctx: TreeComponent, cm: boolean) => {
|
||||
if (cm) {
|
||||
|
@ -258,7 +263,7 @@ describe('recursive components', () => {
|
|||
{
|
||||
if (ctx.data.left != null) {
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, TreeComponent);
|
||||
elementStart(0, 'tree-comp');
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'data', bind(ctx.data.left));
|
||||
|
@ -270,7 +275,7 @@ describe('recursive components', () => {
|
|||
{
|
||||
if (ctx.data.right != null) {
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, TreeComponent);
|
||||
elementStart(0, 'tree-comp');
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'data', bind(ctx.data.right));
|
||||
|
@ -283,6 +288,7 @@ describe('recursive components', () => {
|
|||
});
|
||||
}
|
||||
|
||||
TreeComponent.ngComponentDef.directiveDefs = () => [TreeComponent.ngComponentDef];
|
||||
|
||||
function _buildTree(currDepth: number): TreeNode {
|
||||
const children = currDepth < 2 ? _buildTree(currDepth + 1) : null;
|
||||
|
|
|
@ -31,11 +31,12 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{ text(1, 'content'); }
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent)).toEqual('<child><div>content</div></child>');
|
||||
});
|
||||
|
@ -49,11 +50,12 @@ describe('content projection', () => {
|
|||
});
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{ text(1, 'content'); }
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent)).toEqual('<child>content</child>');
|
||||
});
|
||||
|
@ -70,14 +72,14 @@ describe('content projection', () => {
|
|||
const Child = createComponent('child', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
projectionDef(0);
|
||||
elementStart(1, GrandChild);
|
||||
elementStart(1, 'grand-child');
|
||||
{ projection(2, 0); }
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [GrandChild.ngComponentDef]);
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
elementStart(1, 'b');
|
||||
text(2, 'Hello');
|
||||
|
@ -86,7 +88,8 @@ describe('content projection', () => {
|
|||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent))
|
||||
.toEqual('<child><grand-child><div><b>Hello</b>World!</div></grand-child></child>');
|
||||
|
@ -117,14 +120,15 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', (ctx: any, cm: boolean) => {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
elementStart(1, ProjectedComp);
|
||||
elementStart(1, 'projected-comp');
|
||||
elementEnd();
|
||||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef, ProjectedComp.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent))
|
||||
.toEqual('<child><div><projected-comp>content</projected-comp></div></child>');
|
||||
|
@ -141,7 +145,7 @@ describe('content projection', () => {
|
|||
});
|
||||
const Parent = createComponent('parent', function(ctx: {value: any}, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
text(1, '(');
|
||||
container(2);
|
||||
|
@ -159,7 +163,8 @@ describe('content projection', () => {
|
|||
}
|
||||
}
|
||||
containerRefreshEnd();
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent)).toEqual('<child><div>()</div></child>');
|
||||
parent.value = true;
|
||||
|
@ -179,7 +184,7 @@ describe('content projection', () => {
|
|||
});
|
||||
const Parent = createComponent('parent', function(ctx: {value: any}, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{ container(1); }
|
||||
elementEnd();
|
||||
}
|
||||
|
@ -193,7 +198,8 @@ describe('content projection', () => {
|
|||
}
|
||||
}
|
||||
containerRefreshEnd();
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent)).toEqual('<child></child>');
|
||||
|
||||
|
@ -217,7 +223,7 @@ describe('content projection', () => {
|
|||
});
|
||||
const Parent = createComponent('parent', function(ctx: {value: any}, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
text(1, '(');
|
||||
container(2);
|
||||
|
@ -240,7 +246,8 @@ describe('content projection', () => {
|
|||
}
|
||||
}
|
||||
containerRefreshEnd();
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent)).toEqual('<child><div>(else)</div></child>');
|
||||
parent.value = true;
|
||||
|
@ -289,14 +296,15 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
childCmptInstance = loadDirective(0);
|
||||
text(1, 'content');
|
||||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent)).toEqual('<child><div><span>content</span></div></child>');
|
||||
|
||||
|
@ -340,14 +348,15 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
childCmptInstance = loadDirective(0);
|
||||
text(1, 'content');
|
||||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent)).toEqual('<child><div>content</div></child>');
|
||||
|
||||
|
@ -393,14 +402,15 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
childCmptInstance = loadDirective(0);
|
||||
text(1, 'content');
|
||||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent)).toEqual('<child><div>before-content-after</div></child>');
|
||||
|
||||
|
@ -431,11 +441,12 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{ text(1, 'content'); }
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent)).toEqual('<child><div></div><span>content</span></child>');
|
||||
});
|
||||
|
@ -484,14 +495,15 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
childCmptInstance = loadDirective(0);
|
||||
text(1, 'content');
|
||||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent)).toEqual('<child>content<div></div></child>');
|
||||
|
||||
|
@ -529,7 +541,7 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
elementStart(1, 'span', ['title', 'toFirst']);
|
||||
{ text(2, '1'); }
|
||||
|
@ -540,7 +552,7 @@ describe('content projection', () => {
|
|||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent))
|
||||
|
@ -575,7 +587,7 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
elementStart(1, 'span', ['class', 'toFirst']);
|
||||
{ text(2, '1'); }
|
||||
|
@ -586,7 +598,7 @@ describe('content projection', () => {
|
|||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent))
|
||||
|
@ -621,7 +633,7 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
elementStart(1, 'span', ['class', 'other toFirst']);
|
||||
{ text(2, '1'); }
|
||||
|
@ -632,7 +644,7 @@ describe('content projection', () => {
|
|||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent))
|
||||
|
@ -667,7 +679,7 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
elementStart(1, 'span', ['class', 'toFirst']);
|
||||
{ text(2, '1'); }
|
||||
|
@ -678,7 +690,7 @@ describe('content projection', () => {
|
|||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent))
|
||||
|
@ -711,7 +723,7 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
elementStart(1, 'span', ['class', 'toFirst']);
|
||||
{ text(2, '1'); }
|
||||
|
@ -723,7 +735,7 @@ describe('content projection', () => {
|
|||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent))
|
||||
|
@ -757,7 +769,7 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
elementStart(1, 'span');
|
||||
{ text(2, '1'); }
|
||||
|
@ -769,7 +781,7 @@ describe('content projection', () => {
|
|||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent))
|
||||
|
@ -807,7 +819,7 @@ describe('content projection', () => {
|
|||
const Child = createComponent('child', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
projectionDef(0);
|
||||
elementStart(1, GrandChild);
|
||||
elementStart(1, 'grand-child');
|
||||
{
|
||||
projection(2, 0);
|
||||
elementStart(3, 'span');
|
||||
|
@ -816,7 +828,7 @@ describe('content projection', () => {
|
|||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [GrandChild.ngComponentDef]);
|
||||
|
||||
/**
|
||||
* <child>
|
||||
|
@ -827,7 +839,7 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
elementStart(1, 'span');
|
||||
{ text(2, 'parent content'); }
|
||||
|
@ -835,7 +847,7 @@ describe('content projection', () => {
|
|||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent))
|
||||
|
@ -871,7 +883,7 @@ describe('content projection', () => {
|
|||
const CardWithTitle = createComponent('card-with-title', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
projectionDef(0);
|
||||
elementStart(1, Card);
|
||||
elementStart(1, 'card');
|
||||
{
|
||||
elementStart(2, 'h1', ['card-title', '']);
|
||||
{ text(3, 'Title'); }
|
||||
|
@ -880,7 +892,7 @@ describe('content projection', () => {
|
|||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Card.ngComponentDef]);
|
||||
|
||||
/**
|
||||
* <card-with-title>
|
||||
|
@ -889,11 +901,11 @@ describe('content projection', () => {
|
|||
*/
|
||||
const App = createComponent('app', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, CardWithTitle);
|
||||
elementStart(0, 'card-with-title');
|
||||
{ text(1, 'content'); }
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [CardWithTitle.ngComponentDef]);
|
||||
|
||||
const app = renderComponent(App);
|
||||
expect(toHtml(app))
|
||||
|
@ -930,7 +942,7 @@ describe('content projection', () => {
|
|||
const CardWithTitle = createComponent('card-with-title', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
projectionDef(0);
|
||||
elementStart(1, Card);
|
||||
elementStart(1, 'card');
|
||||
{
|
||||
elementStart(2, 'h1', ['ngProjectAs', '[card-title]']);
|
||||
{ text(3, 'Title'); }
|
||||
|
@ -939,7 +951,7 @@ describe('content projection', () => {
|
|||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Card.ngComponentDef]);
|
||||
|
||||
/**
|
||||
* <card-with-title>
|
||||
|
@ -948,11 +960,11 @@ describe('content projection', () => {
|
|||
*/
|
||||
const App = createComponent('app', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, CardWithTitle);
|
||||
elementStart(0, 'card-with-title');
|
||||
{ text(1, 'content'); }
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [CardWithTitle.ngComponentDef]);
|
||||
|
||||
const app = renderComponent(App);
|
||||
expect(toHtml(app))
|
||||
|
@ -980,7 +992,7 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
elementStart(1, 'div', ['ngProjectAs', 'span']);
|
||||
{ text(2, 'should not project'); }
|
||||
|
@ -991,7 +1003,7 @@ describe('content projection', () => {
|
|||
}
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent)).toEqual('<child><div>should project</div></child>');
|
||||
|
@ -1020,8 +1032,8 @@ describe('content projection', () => {
|
|||
*/
|
||||
const Parent = createComponent('parent', function(ctx: {value: any}, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Child);
|
||||
{ container(1, undefined, undefined, 'div'); }
|
||||
elementStart(0, 'child');
|
||||
{ container(1, undefined, 'div'); }
|
||||
elementEnd();
|
||||
}
|
||||
containerRefreshStart(1);
|
||||
|
@ -1036,7 +1048,7 @@ describe('content projection', () => {
|
|||
}
|
||||
}
|
||||
containerRefreshEnd();
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent)).toEqual('<child><span><div>content</div></span></child>');
|
||||
});
|
||||
|
|
|
@ -6,9 +6,10 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {defineComponent} from '../../src/render3/definition';
|
||||
import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementStart, embeddedViewEnd, embeddedViewStart, text, textBinding} from '../../src/render3/instructions';
|
||||
|
||||
import {renderToHtml} from './render_util';
|
||||
import {ComponentFixture, createComponent, renderToHtml} from './render_util';
|
||||
|
||||
describe('JS control flow', () => {
|
||||
it('should work with if block', () => {
|
||||
|
@ -531,6 +532,136 @@ describe('JS control flow', () => {
|
|||
ctx.condition = true;
|
||||
expect(renderToHtml(Template, ctx)).toEqual('<div><span>Hello</span></div>');
|
||||
});
|
||||
|
||||
it('should work with sibling if blocks with children', () => {
|
||||
let log: string[] = [];
|
||||
|
||||
// Intentionally duplicating the templates in test below so we are
|
||||
// testing the behavior on firstTemplatePass for each of these tests
|
||||
class Comp {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: Comp,
|
||||
selector: [[['comp'], null]],
|
||||
factory: () => {
|
||||
log.push('comp!');
|
||||
return new Comp();
|
||||
},
|
||||
template: function(ctx: Comp, cm: boolean) {}
|
||||
});
|
||||
}
|
||||
|
||||
class App {
|
||||
condition = true;
|
||||
condition2 = true;
|
||||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: App,
|
||||
selector: [[['app'], null]],
|
||||
factory: () => new App(),
|
||||
template: function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div');
|
||||
elementEnd();
|
||||
container(1);
|
||||
container(2);
|
||||
}
|
||||
containerRefreshStart(1);
|
||||
{
|
||||
if (ctx.condition) {
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, 'comp');
|
||||
elementEnd();
|
||||
}
|
||||
embeddedViewEnd();
|
||||
}
|
||||
}
|
||||
containerRefreshEnd();
|
||||
containerRefreshStart(2);
|
||||
{
|
||||
if (ctx.condition2) {
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, 'comp');
|
||||
elementEnd();
|
||||
}
|
||||
embeddedViewEnd();
|
||||
}
|
||||
}
|
||||
containerRefreshEnd();
|
||||
},
|
||||
directiveDefs: () => [Comp.ngComponentDef]
|
||||
});
|
||||
}
|
||||
|
||||
const fixture = new ComponentFixture(App);
|
||||
expect(log).toEqual(['comp!', 'comp!']);
|
||||
});
|
||||
|
||||
it('should work with a sibling if block that starts closed', () => {
|
||||
let log: string[] = [];
|
||||
|
||||
// Intentionally duplicating the templates from above so we are
|
||||
// testing the behavior on firstTemplatePass for each of these tests
|
||||
class Comp {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: Comp,
|
||||
selector: [[['comp'], null]],
|
||||
factory: () => {
|
||||
log.push('comp!');
|
||||
return new Comp();
|
||||
},
|
||||
template: function(ctx: Comp, cm: boolean) {}
|
||||
});
|
||||
}
|
||||
|
||||
class App {
|
||||
condition = false;
|
||||
condition2 = true;
|
||||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: App,
|
||||
selector: [[['app'], null]],
|
||||
factory: () => new App(),
|
||||
template: function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div');
|
||||
elementEnd();
|
||||
container(1);
|
||||
container(2);
|
||||
}
|
||||
containerRefreshStart(1);
|
||||
{
|
||||
if (ctx.condition) {
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, 'comp');
|
||||
elementEnd();
|
||||
}
|
||||
embeddedViewEnd();
|
||||
}
|
||||
}
|
||||
containerRefreshEnd();
|
||||
containerRefreshStart(2);
|
||||
{
|
||||
if (ctx.condition2) {
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, 'comp');
|
||||
elementEnd();
|
||||
}
|
||||
embeddedViewEnd();
|
||||
}
|
||||
}
|
||||
containerRefreshEnd();
|
||||
},
|
||||
directiveDefs: () => [Comp.ngComponentDef]
|
||||
});
|
||||
}
|
||||
|
||||
const fixture = new ComponentFixture(App);
|
||||
expect(log).toEqual(['comp!']);
|
||||
|
||||
fixture.component.condition = true;
|
||||
fixture.update();
|
||||
expect(log).toEqual(['comp!', 'comp!']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('JS for loop', () => {
|
||||
|
|
|
@ -29,6 +29,7 @@ describe('define', () => {
|
|||
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: MyDirective,
|
||||
selector: [[['', 'myDir', ''], null]],
|
||||
factory: () => new MyDirective(),
|
||||
features: [NgOnChangesFeature()],
|
||||
inputs: {valA: 'valA', valB: 'valB'}
|
||||
|
|
|
@ -17,19 +17,20 @@ import {LNodeType} from '../../src/render3/interfaces/node';
|
|||
import {LViewFlags} from '../../src/render3/interfaces/view';
|
||||
import {ViewRef} from '../../src/render3/view_ref';
|
||||
|
||||
import {renderComponent, renderToHtml, toHtml} from './render_util';
|
||||
import {createComponent, createDirective, renderComponent, renderToHtml, toHtml} from './render_util';
|
||||
|
||||
describe('di', () => {
|
||||
describe('no dependencies', () => {
|
||||
it('should create directive with no deps', () => {
|
||||
class Directive {
|
||||
value: string = 'Created';
|
||||
static ngDirectiveDef = defineDirective({type: Directive, factory: () => new Directive});
|
||||
static ngDirectiveDef = defineDirective(
|
||||
{type: Directive, selector: [[['', 'dir', ''], null]], factory: () => new Directive});
|
||||
}
|
||||
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', null, [Directive]);
|
||||
elementStart(0, 'div', ['dir', '']);
|
||||
{ text(1); }
|
||||
elementEnd();
|
||||
}
|
||||
|
@ -37,7 +38,8 @@ describe('di', () => {
|
|||
textBinding(1, bind(loadDirective<Directive>(0).value));
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {})).toEqual('<div>Created</div>');
|
||||
expect(renderToHtml(Template, {}, [Directive.ngDirectiveDef]))
|
||||
.toEqual('<div dir="">Created</div>');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -45,14 +47,22 @@ describe('di', () => {
|
|||
it('should create directive with inter view dependencies', () => {
|
||||
class DirectiveA {
|
||||
value: string = 'A';
|
||||
static ngDirectiveDef = defineDirective(
|
||||
{type: DirectiveA, factory: () => new DirectiveA, features: [PublicFeature]});
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: DirectiveA,
|
||||
selector: [[['', 'dirA', ''], null]],
|
||||
factory: () => new DirectiveA,
|
||||
features: [PublicFeature]
|
||||
});
|
||||
}
|
||||
|
||||
class DirectiveB {
|
||||
value: string = 'B';
|
||||
static ngDirectiveDef = defineDirective(
|
||||
{type: DirectiveB, factory: () => new DirectiveB, features: [PublicFeature]});
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: DirectiveB,
|
||||
selector: [[['', 'dirB', ''], null]],
|
||||
factory: () => new DirectiveB,
|
||||
features: [PublicFeature]
|
||||
});
|
||||
}
|
||||
|
||||
class DirectiveC {
|
||||
|
@ -60,15 +70,16 @@ describe('di', () => {
|
|||
constructor(a: DirectiveA, b: DirectiveB) { this.value = a.value + b.value; }
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: DirectiveC,
|
||||
selector: [[['', 'dirC', ''], null]],
|
||||
factory: () => new DirectiveC(directiveInject(DirectiveA), directiveInject(DirectiveB))
|
||||
});
|
||||
}
|
||||
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', null, [DirectiveA]);
|
||||
elementStart(0, 'div', ['dirA', '']);
|
||||
{
|
||||
elementStart(1, 'span', null, [DirectiveB, DirectiveC]);
|
||||
elementStart(1, 'span', ['dirB', '', 'dirC', '']);
|
||||
{ text(2); }
|
||||
elementEnd();
|
||||
}
|
||||
|
@ -78,7 +89,10 @@ describe('di', () => {
|
|||
textBinding(2, bind(loadDirective<DirectiveC>(2).value));
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {})).toEqual('<div><span>AB</span></div>');
|
||||
const defs =
|
||||
[DirectiveA.ngDirectiveDef, DirectiveB.ngDirectiveDef, DirectiveC.ngDirectiveDef];
|
||||
expect(renderToHtml(Template, {}, defs))
|
||||
.toEqual('<div dira=""><span dirb="" dirc="">AB</span></div>');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -91,6 +105,7 @@ describe('di', () => {
|
|||
}
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: Directive,
|
||||
selector: [[['', 'dir', ''], null]],
|
||||
factory: () => new Directive(injectElementRef()),
|
||||
features: [PublicFeature]
|
||||
});
|
||||
|
@ -103,13 +118,14 @@ describe('di', () => {
|
|||
}
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: DirectiveSameInstance,
|
||||
selector: [[['', 'dirSame', ''], null]],
|
||||
factory: () => new DirectiveSameInstance(injectElementRef(), directiveInject(Directive))
|
||||
});
|
||||
}
|
||||
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', null, [Directive, DirectiveSameInstance]);
|
||||
elementStart(0, 'div', ['dir', '', 'dirSame', '']);
|
||||
{ text(1); }
|
||||
elementEnd();
|
||||
}
|
||||
|
@ -120,7 +136,9 @@ describe('di', () => {
|
|||
loadDirective<DirectiveSameInstance>(1).value, ''));
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {})).toEqual('<div>ElementRef-true</div>');
|
||||
const defs = [Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef];
|
||||
expect(renderToHtml(Template, {}, defs))
|
||||
.toEqual('<div dir="" dirsame="">ElementRef-true</div>');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -133,6 +151,7 @@ describe('di', () => {
|
|||
}
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: Directive,
|
||||
selector: [[['', 'dir', ''], null]],
|
||||
factory: () => new Directive(injectTemplateRef()),
|
||||
features: [PublicFeature]
|
||||
});
|
||||
|
@ -145,6 +164,7 @@ describe('di', () => {
|
|||
}
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: DirectiveSameInstance,
|
||||
selector: [[['', 'dirSame', ''], null]],
|
||||
factory: () => new DirectiveSameInstance(injectTemplateRef(), directiveInject(Directive))
|
||||
});
|
||||
}
|
||||
|
@ -152,7 +172,7 @@ describe('di', () => {
|
|||
|
||||
function Template(ctx: any, cm: any) {
|
||||
if (cm) {
|
||||
container(0, [Directive, DirectiveSameInstance], function() {});
|
||||
container(0, function() {}, undefined, ['dir', '', 'dirSame', '']);
|
||||
text(1);
|
||||
}
|
||||
// TODO: remove loadDirective when removing directive references
|
||||
|
@ -162,7 +182,8 @@ describe('di', () => {
|
|||
loadDirective<DirectiveSameInstance>(1).value, ''));
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {})).toEqual('TemplateRef-true');
|
||||
const defs = [Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef];
|
||||
expect(renderToHtml(Template, {}, defs)).toEqual('TemplateRef-true');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -175,6 +196,7 @@ describe('di', () => {
|
|||
}
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: Directive,
|
||||
selector: [[['', 'dir', ''], null]],
|
||||
factory: () => new Directive(injectViewContainerRef()),
|
||||
features: [PublicFeature]
|
||||
});
|
||||
|
@ -187,6 +209,7 @@ describe('di', () => {
|
|||
}
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: DirectiveSameInstance,
|
||||
selector: [[['', 'dirSame', ''], null]],
|
||||
factory:
|
||||
() => new DirectiveSameInstance(injectViewContainerRef(), directiveInject(Directive))
|
||||
});
|
||||
|
@ -194,7 +217,7 @@ describe('di', () => {
|
|||
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', null, [Directive, DirectiveSameInstance]);
|
||||
elementStart(0, 'div', ['dir', '', 'dirSame', '']);
|
||||
{ text(1); }
|
||||
elementEnd();
|
||||
}
|
||||
|
@ -205,7 +228,9 @@ describe('di', () => {
|
|||
loadDirective<DirectiveSameInstance>(1).value, ''));
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {})).toEqual('<div>ViewContainerRef-true</div>');
|
||||
const defs = [Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef];
|
||||
expect(renderToHtml(Template, {}, defs))
|
||||
.toEqual('<div dir="" dirsame="">ViewContainerRef-true</div>');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -219,7 +244,7 @@ describe('di', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyComp,
|
||||
tag: 'my-comp',
|
||||
selector: [[['my-comp'], null]],
|
||||
factory: () => comp = new MyComp(injectChangeDetectorRef()),
|
||||
template: function(ctx: MyComp, cm: boolean) {
|
||||
if (cm) {
|
||||
|
@ -235,6 +260,7 @@ describe('di', () => {
|
|||
constructor(public cdr: ChangeDetectorRef) { this.value = (cdr.constructor as any).name; }
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: Directive,
|
||||
selector: [[['', 'dir', ''], null]],
|
||||
factory: () => dir = new Directive(injectChangeDetectorRef()),
|
||||
features: [PublicFeature],
|
||||
exportAs: 'dir'
|
||||
|
@ -246,34 +272,53 @@ describe('di', () => {
|
|||
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: DirectiveSameInstance,
|
||||
selector: [[['', 'dirSame', ''], null]],
|
||||
factory: () => dirSameInstance = new DirectiveSameInstance(injectChangeDetectorRef())
|
||||
});
|
||||
}
|
||||
|
||||
const $e0_attrs$ = ['dir', '', 'dirSameInstance', ''];
|
||||
class IfDirective {
|
||||
/* @Input */
|
||||
myIf = true;
|
||||
|
||||
constructor(public template: TemplateRef<any>, public vcr: ViewContainerRef) {}
|
||||
|
||||
ngOnChanges() {
|
||||
if (this.myIf) {
|
||||
this.vcr.createEmbeddedView(this.template);
|
||||
}
|
||||
}
|
||||
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: IfDirective,
|
||||
selector: [[['', 'myIf', ''], null]],
|
||||
factory: () => new IfDirective(injectTemplateRef(), injectViewContainerRef()),
|
||||
inputs: {myIf: 'myIf'},
|
||||
features: [PublicFeature, NgOnChangesFeature()]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const defs = [
|
||||
MyComp.ngComponentDef, Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef,
|
||||
IfDirective.ngDirectiveDef
|
||||
];
|
||||
|
||||
it('should inject current component ChangeDetectorRef into directives on components', () => {
|
||||
class MyApp {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
factory: () => new MyApp(),
|
||||
/** <my-comp dir dirSameInstance #dir="dir"></my-comp> {{ dir.value }} */
|
||||
template: function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, MyComp, $e0_attrs$, [Directive, DirectiveSameInstance]);
|
||||
elementEnd();
|
||||
text(1);
|
||||
}
|
||||
// TODO: remove loadDirective when removing directive references
|
||||
textBinding(1, bind(loadDirective<Directive>(1).value));
|
||||
}
|
||||
});
|
||||
}
|
||||
/** <my-comp dir dirSameInstance #dir="dir"></my-comp> {{ dir.value }} */
|
||||
const MyApp = createComponent('my-app', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'my-comp', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
|
||||
elementEnd();
|
||||
text(1);
|
||||
}
|
||||
// TODO: remove loadDirective when removing directive references
|
||||
textBinding(1, bind(loadDirective<Directive>(1).value));
|
||||
}, defs);
|
||||
|
||||
const app = renderComponent(MyApp);
|
||||
// ChangeDetectorRef is the token, ViewRef has historically been the constructor
|
||||
expect(toHtml(app)).toEqual('<my-comp dir="" dirsameinstance=""></my-comp>ViewRef');
|
||||
expect(toHtml(app)).toEqual('<my-comp dir="" dirsame=""></my-comp>ViewRef');
|
||||
expect((comp !.cdr as ViewRef<MyComp>).context).toBe(comp);
|
||||
|
||||
expect(dir !.cdr).toBe(comp !.cdr);
|
||||
|
@ -287,23 +332,24 @@ describe('di', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: () => new MyApp(injectChangeDetectorRef()),
|
||||
/** <div dir dirSameInstance #dir="dir"> {{ dir.value }} </div> */
|
||||
template: function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', $e0_attrs$, [Directive, DirectiveSameInstance]);
|
||||
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
|
||||
{ text(1); }
|
||||
elementEnd();
|
||||
}
|
||||
// TODO: remove loadDirective when removing directive references
|
||||
textBinding(1, bind(loadDirective<Directive>(0).value));
|
||||
}
|
||||
},
|
||||
directiveDefs: defs
|
||||
});
|
||||
}
|
||||
|
||||
const app = renderComponent(MyApp);
|
||||
expect(toHtml(app)).toEqual('<div dir="" dirsameinstance="">ViewRef</div>');
|
||||
expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>');
|
||||
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
|
||||
|
||||
expect(dir !.cdr).toBe(app.cdr);
|
||||
|
@ -316,7 +362,7 @@ describe('di', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: () => new MyApp(injectChangeDetectorRef()),
|
||||
/**
|
||||
* <my-comp>
|
||||
|
@ -326,9 +372,9 @@ describe('di', () => {
|
|||
*/
|
||||
template: function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, MyComp);
|
||||
elementStart(0, 'my-comp');
|
||||
{
|
||||
elementStart(1, 'div', $e0_attrs$, [Directive, DirectiveSameInstance]);
|
||||
elementStart(1, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
|
||||
elementEnd();
|
||||
}
|
||||
elementEnd();
|
||||
|
@ -336,13 +382,13 @@ describe('di', () => {
|
|||
}
|
||||
// TODO: remove loadDirective when removing directive references
|
||||
textBinding(2, bind(loadDirective<Directive>(1).value));
|
||||
}
|
||||
},
|
||||
directiveDefs: defs
|
||||
});
|
||||
}
|
||||
|
||||
const app = renderComponent(MyApp);
|
||||
expect(toHtml(app))
|
||||
.toEqual('<my-comp><div dir="" dirsameinstance=""></div></my-comp>ViewRef');
|
||||
expect(toHtml(app)).toEqual('<my-comp><div dir="" dirsame=""></div></my-comp>ViewRef');
|
||||
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
|
||||
|
||||
expect(dir !.cdr).toBe(app !.cdr);
|
||||
|
@ -358,7 +404,7 @@ describe('di', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: () => new MyApp(injectChangeDetectorRef()),
|
||||
/**
|
||||
* % if (showing) {
|
||||
|
@ -373,7 +419,7 @@ describe('di', () => {
|
|||
{
|
||||
if (ctx.showing) {
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, 'div', $e0_attrs$, [Directive, DirectiveSameInstance]);
|
||||
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
|
||||
{ text(1); }
|
||||
elementEnd();
|
||||
}
|
||||
|
@ -383,12 +429,13 @@ describe('di', () => {
|
|||
embeddedViewEnd();
|
||||
}
|
||||
containerRefreshEnd();
|
||||
}
|
||||
},
|
||||
directiveDefs: defs
|
||||
});
|
||||
}
|
||||
|
||||
const app = renderComponent(MyApp);
|
||||
expect(toHtml(app)).toEqual('<div dir="" dirsameinstance="">ViewRef</div>');
|
||||
expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>');
|
||||
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
|
||||
|
||||
expect(dir !.cdr).toBe(app.cdr);
|
||||
|
@ -396,26 +443,6 @@ describe('di', () => {
|
|||
});
|
||||
|
||||
it('should inject host component ChangeDetectorRef into directives on containers', () => {
|
||||
class IfDirective {
|
||||
/* @Input */
|
||||
myIf = true;
|
||||
|
||||
constructor(public template: TemplateRef<any>, public vcr: ViewContainerRef) {}
|
||||
|
||||
ngOnChanges() {
|
||||
if (this.myIf) {
|
||||
this.vcr.createEmbeddedView(this.template);
|
||||
}
|
||||
}
|
||||
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: IfDirective,
|
||||
factory: () => new IfDirective(injectTemplateRef(), injectViewContainerRef()),
|
||||
inputs: {myIf: 'myIf'},
|
||||
features: [PublicFeature, NgOnChangesFeature()]
|
||||
});
|
||||
}
|
||||
|
||||
class MyApp {
|
||||
showing = true;
|
||||
|
||||
|
@ -423,31 +450,32 @@ describe('di', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: () => new MyApp(injectChangeDetectorRef()),
|
||||
/** <div *myIf="showing" dir dirSameInstance #dir="dir"> {{ dir.value }} </div> */
|
||||
template: function(ctx: MyApp, cm: boolean) {
|
||||
if (cm) {
|
||||
container(0, [IfDirective], C1);
|
||||
container(0, C1, undefined, ['myIf', 'showing']);
|
||||
}
|
||||
containerRefreshStart(0);
|
||||
containerRefreshEnd();
|
||||
|
||||
function C1(ctx1: any, cm1: boolean) {
|
||||
if (cm1) {
|
||||
elementStart(0, 'div', $e0_attrs$, [Directive, DirectiveSameInstance]);
|
||||
elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']);
|
||||
{ text(1); }
|
||||
elementEnd();
|
||||
}
|
||||
// TODO: remove loadDirective when removing directive references
|
||||
textBinding(1, bind(loadDirective<Directive>(0).value));
|
||||
}
|
||||
}
|
||||
},
|
||||
directiveDefs: defs
|
||||
});
|
||||
}
|
||||
|
||||
const app = renderComponent(MyApp);
|
||||
expect(toHtml(app)).toEqual('<div dir="" dirsameinstance="">ViewRef</div>');
|
||||
expect(toHtml(app)).toEqual('<div dir="" dirsame="">ViewRef</div>');
|
||||
expect((app !.cdr as ViewRef<MyApp>).context).toBe(app);
|
||||
|
||||
expect(dir !.cdr).toBe(app.cdr);
|
||||
|
@ -457,20 +485,14 @@ describe('di', () => {
|
|||
it('should injectAttribute', () => {
|
||||
let exist: string|undefined = 'wrong';
|
||||
let nonExist: string|undefined = 'wrong';
|
||||
class MyApp {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
factory: () => new MyApp(),
|
||||
template: function(ctx: MyApp, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', ['exist', 'existValue', 'other', 'ignore']);
|
||||
exist = injectAttribute('exist');
|
||||
nonExist = injectAttribute('nonExist');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const MyApp = createComponent('my-app', function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', ['exist', 'existValue', 'other', 'ignore']);
|
||||
exist = injectAttribute('exist');
|
||||
nonExist = injectAttribute('nonExist');
|
||||
}
|
||||
});
|
||||
|
||||
const app = renderComponent(MyApp);
|
||||
expect(exist).toEqual('existValue');
|
||||
|
@ -557,7 +579,7 @@ describe('di', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyApp,
|
||||
tag: 'my-app',
|
||||
selector: [[['my-app'], null]],
|
||||
factory: () => new MyApp(
|
||||
directiveInject(String as any, InjectFlags.Default, 'DefaultValue')),
|
||||
template: () => null
|
||||
|
@ -569,21 +591,14 @@ describe('di', () => {
|
|||
});
|
||||
|
||||
it('should inject from parent view', () => {
|
||||
class ParentDirective {
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: ParentDirective,
|
||||
factory: () => new ParentDirective(),
|
||||
features: [PublicFeature]
|
||||
});
|
||||
}
|
||||
const ParentDirective = createDirective('parentDir');
|
||||
|
||||
class ChildDirective {
|
||||
value: string;
|
||||
constructor(public parent: ParentDirective) {
|
||||
this.value = (parent.constructor as any).name;
|
||||
}
|
||||
constructor(public parent: any) { this.value = (parent.constructor as any).name; }
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: ChildDirective,
|
||||
selector: [[['', 'childDir', ''], null]],
|
||||
factory: () => new ChildDirective(directiveInject(ParentDirective)),
|
||||
features: [PublicFeature]
|
||||
});
|
||||
|
@ -591,10 +606,9 @@ describe('di', () => {
|
|||
|
||||
class Child2Directive {
|
||||
value: boolean;
|
||||
constructor(parent: ParentDirective, child: ChildDirective) {
|
||||
this.value = parent === child.parent;
|
||||
}
|
||||
constructor(parent: any, child: ChildDirective) { this.value = parent === child.parent; }
|
||||
static ngDirectiveDef = defineDirective({
|
||||
selector: [[['', 'child2Dir', ''], null]],
|
||||
type: Child2Directive,
|
||||
factory: () => new Child2Directive(
|
||||
directiveInject(ParentDirective), directiveInject(ChildDirective))
|
||||
|
@ -603,14 +617,14 @@ describe('di', () => {
|
|||
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', null, [ParentDirective]);
|
||||
elementStart(0, 'div', ['parentDir', '']);
|
||||
{ container(1); }
|
||||
elementEnd();
|
||||
}
|
||||
containerRefreshStart(1);
|
||||
{
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, 'span', null, [ChildDirective, Child2Directive]);
|
||||
elementStart(0, 'span', ['childDir', '', 'child2Dir', '']);
|
||||
{ text(1); }
|
||||
elementEnd();
|
||||
}
|
||||
|
@ -624,7 +638,12 @@ describe('di', () => {
|
|||
containerRefreshEnd();
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {})).toEqual('<div><span>ParentDirective-true</span></div>');
|
||||
const defs = [
|
||||
ChildDirective.ngDirectiveDef, Child2Directive.ngDirectiveDef,
|
||||
ParentDirective.ngDirectiveDef
|
||||
];
|
||||
expect(renderToHtml(Template, {}, defs))
|
||||
.toEqual('<div parentdir=""><span child2dir="" childdir="">Directive-true</span></div>');
|
||||
});
|
||||
|
||||
it('should inject from module Injector', () => {
|
||||
|
@ -635,7 +654,7 @@ describe('di', () => {
|
|||
describe('getOrCreateNodeInjector', () => {
|
||||
it('should handle initial undefined state', () => {
|
||||
const contentView =
|
||||
createLView(-1, null !, createTView(), null, null, LViewFlags.CheckAlways);
|
||||
createLView(-1, null !, createTView(null), null, null, LViewFlags.CheckAlways);
|
||||
const oldView = enterView(contentView, null !);
|
||||
try {
|
||||
const parent = createLNode(0, LNodeType.Element, null, null);
|
||||
|
|
|
@ -22,6 +22,7 @@ describe('directive', () => {
|
|||
klass = 'foo';
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: Directive,
|
||||
selector: [[['', 'dir', ''], null]],
|
||||
factory: () => directiveInstance = new Directive,
|
||||
hostBindings: (directiveIndex: number, elementIndex: number) => {
|
||||
elementProperty(
|
||||
|
@ -32,14 +33,15 @@ describe('directive', () => {
|
|||
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'span', null, [Directive]);
|
||||
elementStart(0, 'span', ['dir', '']);
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {})).toEqual('<span class="foo"></span>');
|
||||
const defs = [Directive.ngDirectiveDef];
|
||||
expect(renderToHtml(Template, {}, defs)).toEqual('<span class="foo" dir=""></span>');
|
||||
directiveInstance !.klass = 'bar';
|
||||
expect(renderToHtml(Template, {})).toEqual('<span class="bar"></span>');
|
||||
expect(renderToHtml(Template, {}, defs)).toEqual('<span class="bar" dir=""></span>');
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ describe('exports', () => {
|
|||
/** <input value="one" #myInput> {{ myInput.value }} */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'input', ['value', 'one'], null, ['myInput', '']);
|
||||
elementStart(0, 'input', ['value', 'one'], ['myInput', '']);
|
||||
elementEnd();
|
||||
text(1);
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ describe('exports', () => {
|
|||
/** <comp #myComp></comp> {{ myComp.name }} */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, MyComponent, null, null, ['myComp', '']);
|
||||
elementStart(0, 'comp', null, ['myComp', '']);
|
||||
elementEnd();
|
||||
text(1);
|
||||
}
|
||||
|
@ -46,13 +46,13 @@ describe('exports', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'comp',
|
||||
selector: [[['comp'], null]],
|
||||
template: function() {},
|
||||
factory: () => new MyComponent
|
||||
});
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {})).toEqual('<comp></comp>Nancy');
|
||||
expect(renderToHtml(Template, {}, [MyComponent.ngComponentDef])).toEqual('<comp></comp>Nancy');
|
||||
});
|
||||
|
||||
it('should support component instance fed into directive', () => {
|
||||
|
@ -63,7 +63,7 @@ describe('exports', () => {
|
|||
constructor() { myComponent = this; }
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'comp',
|
||||
selector: [[['comp'], null]],
|
||||
template: function() {},
|
||||
factory: () => new MyComponent
|
||||
});
|
||||
|
@ -72,23 +72,29 @@ describe('exports', () => {
|
|||
class MyDir {
|
||||
myDir: MyComponent;
|
||||
constructor() { myDir = this; }
|
||||
static ngDirectiveDef =
|
||||
defineDirective({type: MyDir, factory: () => new MyDir, inputs: {myDir: 'myDir'}});
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: MyDir,
|
||||
selector: [[['', 'myDir', ''], null]],
|
||||
factory: () => new MyDir,
|
||||
inputs: {myDir: 'myDir'}
|
||||
});
|
||||
}
|
||||
|
||||
const defs = [MyComponent.ngComponentDef, MyDir.ngDirectiveDef];
|
||||
|
||||
/** <comp #myComp></comp> <div [myDir]="myComp"></div> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, MyComponent, null, null, ['myComp', '']);
|
||||
elementStart(0, 'comp', null, ['myComp', '']);
|
||||
elementEnd();
|
||||
elementStart(1, 'div', null, [MyDir]);
|
||||
elementStart(1, 'div', ['myDir', '']);
|
||||
elementEnd();
|
||||
}
|
||||
// TODO: replace loadDirective when removing directive refs
|
||||
elementProperty(1, 'myDir', bind(loadDirective<MyComponent>(0)));
|
||||
}
|
||||
|
||||
renderToHtml(Template, {});
|
||||
renderToHtml(Template, {}, defs);
|
||||
expect(myDir !.myDir).toEqual(myComponent !);
|
||||
});
|
||||
|
||||
|
@ -97,7 +103,7 @@ describe('exports', () => {
|
|||
/** <div someDir #myDir="someDir"></div> {{ myDir.name }} */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', null, [SomeDir], ['myDir', 'someDir']);
|
||||
elementStart(0, 'div', ['someDir', ''], ['myDir', 'someDir']);
|
||||
elementEnd();
|
||||
text(1);
|
||||
}
|
||||
|
@ -107,11 +113,16 @@ describe('exports', () => {
|
|||
|
||||
class SomeDir {
|
||||
name = 'Drew';
|
||||
static ngDirectiveDef =
|
||||
defineDirective({type: SomeDir, factory: () => new SomeDir, exportAs: 'someDir'});
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: SomeDir,
|
||||
selector: [[['', 'someDir', ''], null]],
|
||||
factory: () => new SomeDir,
|
||||
exportAs: 'someDir'
|
||||
});
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {})).toEqual('<div></div>Drew');
|
||||
expect(renderToHtml(Template, {}, [SomeDir.ngDirectiveDef]))
|
||||
.toEqual('<div somedir=""></div>Drew');
|
||||
});
|
||||
|
||||
describe('forward refs', () => {
|
||||
|
@ -120,7 +131,7 @@ describe('exports', () => {
|
|||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
text(0);
|
||||
elementStart(1, 'input', ['value', 'one'], null, ['myInput', '']);
|
||||
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
|
||||
elementEnd();
|
||||
}
|
||||
let myInput = elementStart(1);
|
||||
|
@ -137,7 +148,7 @@ describe('exports', () => {
|
|||
if (cm) {
|
||||
elementStart(0, 'div');
|
||||
elementEnd();
|
||||
elementStart(1, 'input', ['value', 'one'], null, ['myInput', '']);
|
||||
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
|
||||
elementEnd();
|
||||
}
|
||||
let myInput = elementStart(1);
|
||||
|
@ -153,7 +164,7 @@ describe('exports', () => {
|
|||
if (cm) {
|
||||
elementStart(0, 'div');
|
||||
elementEnd();
|
||||
elementStart(1, 'input', ['value', 'one'], null, ['myInput', '']);
|
||||
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
|
||||
elementEnd();
|
||||
}
|
||||
let myInput = elementStart(1);
|
||||
|
@ -169,7 +180,7 @@ describe('exports', () => {
|
|||
if (cm) {
|
||||
elementStart(0, 'div');
|
||||
elementEnd();
|
||||
elementStart(1, 'input', ['type', 'checkbox', 'checked', 'true'], null, ['myInput', '']);
|
||||
elementStart(1, 'input', ['type', 'checkbox', 'checked', 'true'], ['myInput', '']);
|
||||
elementEnd();
|
||||
}
|
||||
let myInput = elementStart(1);
|
||||
|
@ -190,7 +201,7 @@ describe('exports', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'comp',
|
||||
selector: [[['comp'], null]],
|
||||
template: function(ctx: MyComponent, cm: boolean) {},
|
||||
factory: () => new MyComponent
|
||||
});
|
||||
|
@ -201,23 +212,27 @@ describe('exports', () => {
|
|||
|
||||
constructor() { myDir = this; }
|
||||
|
||||
static ngDirectiveDef =
|
||||
defineDirective({type: MyDir, factory: () => new MyDir, inputs: {myDir: 'myDir'}});
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: MyDir,
|
||||
selector: [[['', 'myDir', ''], null]],
|
||||
factory: () => new MyDir,
|
||||
inputs: {myDir: 'myDir'}
|
||||
});
|
||||
}
|
||||
|
||||
/** <div [myDir]="myComp"></div><comp #myComp></comp> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', null, [MyDir]);
|
||||
elementStart(0, 'div', ['myDir', '']);
|
||||
elementEnd();
|
||||
elementStart(1, MyComponent, null, null, ['myComp', '']);
|
||||
elementStart(1, 'comp', null, ['myComp', '']);
|
||||
elementEnd();
|
||||
}
|
||||
// TODO: replace loadDirective when removing directive refs
|
||||
elementProperty(0, 'myDir', bind(loadDirective<MyComponent>(1)));
|
||||
}
|
||||
|
||||
renderToHtml(Template, {});
|
||||
renderToHtml(Template, {}, [MyComponent.ngComponentDef, MyDir.ngDirectiveDef]);
|
||||
expect(myDir !.myDir).toEqual(myComponent !);
|
||||
});
|
||||
|
||||
|
@ -228,9 +243,9 @@ describe('exports', () => {
|
|||
if (cm) {
|
||||
text(0);
|
||||
text(1);
|
||||
elementStart(2, MyComponent, null, null, ['myComp', '']);
|
||||
elementStart(2, 'comp', null, ['myComp', '']);
|
||||
elementEnd();
|
||||
elementStart(3, 'input', ['value', 'one'], null, ['myInput', '']);
|
||||
elementStart(3, 'input', ['value', 'one'], ['myInput', '']);
|
||||
elementEnd();
|
||||
}
|
||||
let myInput = elementStart(3);
|
||||
|
@ -249,12 +264,13 @@ describe('exports', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyComponent,
|
||||
tag: 'comp',
|
||||
selector: [[['comp'], null]],
|
||||
template: function() {},
|
||||
factory: () => new MyComponent
|
||||
});
|
||||
}
|
||||
expect(renderToHtml(Template, {})).toEqual('oneNancy<comp></comp><input value="one">');
|
||||
expect(renderToHtml(Template, {}, [MyComponent.ngComponentDef]))
|
||||
.toEqual('oneNancy<comp></comp><input value="one">');
|
||||
});
|
||||
|
||||
it('should work inside a view container', () => {
|
||||
|
@ -271,7 +287,7 @@ describe('exports', () => {
|
|||
{
|
||||
if (cm1) {
|
||||
text(0);
|
||||
elementStart(1, 'input', ['value', 'one'], null, ['myInput', '']);
|
||||
elementStart(1, 'input', ['value', 'one'], ['myInput', '']);
|
||||
elementEnd();
|
||||
}
|
||||
let myInput = elementStart(1);
|
||||
|
|
|
@ -178,7 +178,7 @@ describe('render3 integration test', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: TodoComponent,
|
||||
tag: 'todo',
|
||||
selector: [[['todo'], null]],
|
||||
template: function TodoTemplate(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'p');
|
||||
|
@ -194,26 +194,28 @@ describe('render3 integration test', () => {
|
|||
});
|
||||
}
|
||||
|
||||
const defs = [TodoComponent.ngComponentDef];
|
||||
|
||||
it('should support a basic component template', () => {
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, TodoComponent);
|
||||
elementStart(0, 'todo');
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, null)).toEqual('<todo><p>Todo one</p></todo>');
|
||||
expect(renderToHtml(Template, null, defs)).toEqual('<todo><p>Todo one</p></todo>');
|
||||
});
|
||||
|
||||
it('should support a component template with sibling', () => {
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, TodoComponent);
|
||||
elementStart(0, 'todo');
|
||||
elementEnd();
|
||||
text(1, 'two');
|
||||
}
|
||||
}
|
||||
expect(renderToHtml(Template, null)).toEqual('<todo><p>Todo one</p></todo>two');
|
||||
expect(renderToHtml(Template, null, defs)).toEqual('<todo><p>Todo one</p></todo>two');
|
||||
});
|
||||
|
||||
it('should support a component template with component sibling', () => {
|
||||
|
@ -223,13 +225,13 @@ describe('render3 integration test', () => {
|
|||
*/
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, TodoComponent);
|
||||
elementStart(0, 'todo');
|
||||
elementEnd();
|
||||
elementStart(1, TodoComponent);
|
||||
elementStart(1, 'todo');
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
expect(renderToHtml(Template, null))
|
||||
expect(renderToHtml(Template, null, defs))
|
||||
.toEqual('<todo><p>Todo one</p></todo><todo><p>Todo one</p></todo>');
|
||||
});
|
||||
|
||||
|
@ -240,7 +242,7 @@ describe('render3 integration test', () => {
|
|||
title = 'one';
|
||||
static ngComponentDef = defineComponent({
|
||||
type: TodoComponentHostBinding,
|
||||
tag: 'todo',
|
||||
selector: [[['todo'], null]],
|
||||
template: function TodoComponentHostBindingTemplate(
|
||||
ctx: TodoComponentHostBinding, cm: boolean) {
|
||||
if (cm) {
|
||||
|
@ -260,21 +262,22 @@ describe('render3 integration test', () => {
|
|||
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, TodoComponentHostBinding);
|
||||
elementStart(0, 'todo');
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {})).toEqual('<todo title="one">one</todo>');
|
||||
const defs = [TodoComponentHostBinding.ngComponentDef];
|
||||
expect(renderToHtml(Template, {}, defs)).toEqual('<todo title="one">one</todo>');
|
||||
cmptInstance !.title = 'two';
|
||||
expect(renderToHtml(Template, {})).toEqual('<todo title="two">two</todo>');
|
||||
expect(renderToHtml(Template, {}, defs)).toEqual('<todo title="two">two</todo>');
|
||||
});
|
||||
|
||||
it('should support root component with host attribute', () => {
|
||||
class HostAttributeComp {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: HostAttributeComp,
|
||||
tag: 'host-attr-comp',
|
||||
selector: [[['host-attr-comp'], null]],
|
||||
factory: () => new HostAttributeComp(),
|
||||
template: (ctx: HostAttributeComp, cm: boolean) => {},
|
||||
attributes: ['role', 'button']
|
||||
|
@ -291,7 +294,7 @@ describe('render3 integration test', () => {
|
|||
name = 'Bess';
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyComp,
|
||||
tag: 'comp',
|
||||
selector: [[['comp'], null]],
|
||||
template: function MyCompTemplate(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'p');
|
||||
|
@ -306,12 +309,13 @@ describe('render3 integration test', () => {
|
|||
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, MyComp);
|
||||
elementStart(0, 'comp');
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, null)).toEqual('<comp><p>Bess</p></comp>');
|
||||
expect(renderToHtml(Template, null, [MyComp.ngComponentDef]))
|
||||
.toEqual('<comp><p>Bess</p></comp>');
|
||||
});
|
||||
|
||||
it('should support a component with sub-views', () => {
|
||||
|
@ -324,7 +328,7 @@ describe('render3 integration test', () => {
|
|||
condition: boolean;
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyComp,
|
||||
tag: 'comp',
|
||||
selector: [[['comp'], null]],
|
||||
template: function MyCompTemplate(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
container(0);
|
||||
|
@ -350,14 +354,16 @@ describe('render3 integration test', () => {
|
|||
/** <comp [condition]="condition"></comp> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, MyComp);
|
||||
elementStart(0, 'comp');
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'condition', bind(ctx.condition));
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {condition: true})).toEqual('<comp><div>text</div></comp>');
|
||||
expect(renderToHtml(Template, {condition: false})).toEqual('<comp></comp>');
|
||||
const defs = [MyComp.ngComponentDef];
|
||||
expect(renderToHtml(Template, {condition: true}, defs))
|
||||
.toEqual('<comp><div>text</div></comp>');
|
||||
expect(renderToHtml(Template, {condition: false}, defs)).toEqual('<comp></comp>');
|
||||
|
||||
});
|
||||
|
||||
|
@ -428,7 +434,7 @@ describe('render3 integration test', () => {
|
|||
beforeTree: Tree;
|
||||
afterTree: Tree;
|
||||
static ngComponentDef = defineComponent({
|
||||
tag: 'child',
|
||||
selector: [[['child'], null]],
|
||||
type: ChildComponent,
|
||||
template: function ChildComponentTemplate(
|
||||
ctx: {beforeTree: Tree, afterTree: Tree}, cm: boolean) {
|
||||
|
@ -460,7 +466,7 @@ describe('render3 integration test', () => {
|
|||
|
||||
function parentTemplate(ctx: ParentCtx, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, ChildComponent);
|
||||
elementStart(0, 'child');
|
||||
{ container(1); }
|
||||
elementEnd();
|
||||
}
|
||||
|
@ -482,14 +488,15 @@ describe('render3 integration test', () => {
|
|||
projectedTree: {beforeLabel: 'p'},
|
||||
afterTree: {afterLabel: 'z'}
|
||||
};
|
||||
expect(renderToHtml(parentTemplate, ctx)).toEqual('<child>apz</child>');
|
||||
const defs = [ChildComponent.ngComponentDef];
|
||||
expect(renderToHtml(parentTemplate, ctx, defs)).toEqual('<child>apz</child>');
|
||||
ctx.projectedTree = {subTrees: [{}, {}, {subTrees: [{}, {}]}, {}]};
|
||||
ctx.beforeTree.subTrees !.push({afterLabel: 'b'});
|
||||
expect(renderToHtml(parentTemplate, ctx)).toEqual('<child>abz</child>');
|
||||
expect(renderToHtml(parentTemplate, ctx, defs)).toEqual('<child>abz</child>');
|
||||
ctx.projectedTree.subTrees ![1].afterLabel = 'h';
|
||||
expect(renderToHtml(parentTemplate, ctx)).toEqual('<child>abhz</child>');
|
||||
expect(renderToHtml(parentTemplate, ctx, defs)).toEqual('<child>abhz</child>');
|
||||
ctx.beforeTree.subTrees !.push({beforeLabel: 'c'});
|
||||
expect(renderToHtml(parentTemplate, ctx)).toEqual('<child>abchz</child>');
|
||||
expect(renderToHtml(parentTemplate, ctx, defs)).toEqual('<child>abchz</child>');
|
||||
|
||||
// To check the context easily:
|
||||
// console.log(JSON.stringify(ctx));
|
||||
|
@ -633,6 +640,7 @@ describe('render3 integration test', () => {
|
|||
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: HostBindingDir,
|
||||
selector: [[['', 'hostBindingDir', ''], null]],
|
||||
factory: function HostBindingDir_Factory() {
|
||||
return hostBindingDir = new HostBindingDir();
|
||||
},
|
||||
|
@ -645,16 +653,17 @@ describe('render3 integration test', () => {
|
|||
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', ['hostBindingDir', ''], [HostBindingDir]);
|
||||
elementStart(0, 'div', ['hostBindingDir', '']);
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {}))
|
||||
const defs = [HostBindingDir.ngDirectiveDef];
|
||||
expect(renderToHtml(Template, {}, defs))
|
||||
.toEqual(`<div aria-label="some label" hostbindingdir=""></div>`);
|
||||
|
||||
hostBindingDir !.label = 'other label';
|
||||
expect(renderToHtml(Template, {}))
|
||||
expect(renderToHtml(Template, {}, defs))
|
||||
.toEqual(`<div aria-label="other label" hostbindingdir=""></div>`);
|
||||
});
|
||||
});
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -24,7 +24,7 @@ describe('event listeners', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyComp,
|
||||
tag: 'comp',
|
||||
selector: [[['comp'], null]],
|
||||
/** <button (click)="onClick()"> Click me </button> */
|
||||
template: function CompTemplate(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
|
@ -61,7 +61,7 @@ describe('event listeners', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: PreventDefaultComp,
|
||||
tag: 'prevent-default-comp',
|
||||
selector: [[['prevent-default-comp'], null]],
|
||||
factory: () => new PreventDefaultComp(),
|
||||
/** <button (click)="onClick($event)">Click</button> */
|
||||
template: (ctx: PreventDefaultComp, cm: boolean) => {
|
||||
|
@ -235,6 +235,7 @@ describe('event listeners', () => {
|
|||
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: HostListenerDir,
|
||||
selector: [[['', 'hostListenerDir', ''], null]],
|
||||
factory: function HostListenerDir_Factory() {
|
||||
const $dir$ = new HostListenerDir();
|
||||
listener('click', function() { return $dir$.onClick(); });
|
||||
|
@ -245,13 +246,13 @@ describe('event listeners', () => {
|
|||
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'button', ['hostListenerDir', ''], [HostListenerDir]);
|
||||
elementStart(0, 'button', ['hostListenerDir', '']);
|
||||
text(1, 'Click');
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
||||
renderToHtml(Template, {});
|
||||
renderToHtml(Template, {}, [HostListenerDir.ngDirectiveDef]);
|
||||
const button = containerEl.querySelector('button') !;
|
||||
button.click();
|
||||
expect(events).toEqual(['click!']);
|
||||
|
@ -337,9 +338,9 @@ describe('event listeners', () => {
|
|||
if (ctx.showing) {
|
||||
if (embeddedViewStart(0)) {
|
||||
text(0, 'Hello');
|
||||
elementStart(1, MyComp);
|
||||
elementStart(1, 'comp');
|
||||
elementEnd();
|
||||
elementStart(2, MyComp);
|
||||
elementStart(2, 'comp');
|
||||
elementEnd();
|
||||
}
|
||||
embeddedViewEnd();
|
||||
|
@ -349,7 +350,7 @@ describe('event listeners', () => {
|
|||
}
|
||||
|
||||
const ctx = {showing: true};
|
||||
renderToHtml(Template, ctx);
|
||||
renderToHtml(Template, ctx, [MyComp.ngComponentDef]);
|
||||
const buttons = containerEl.querySelectorAll('button') !;
|
||||
|
||||
buttons[0].click();
|
||||
|
@ -360,7 +361,7 @@ describe('event listeners', () => {
|
|||
|
||||
// the child view listener should be removed when the parent view is removed
|
||||
ctx.showing = false;
|
||||
renderToHtml(Template, ctx);
|
||||
renderToHtml(Template, ctx, [MyComp.ngComponentDef]);
|
||||
buttons[0].click();
|
||||
buttons[1].click();
|
||||
expect(comps[0] !.counter).toEqual(1);
|
||||
|
|
|
@ -15,6 +15,8 @@ import {containerEl, renderToHtml} from './render_util';
|
|||
|
||||
describe('outputs', () => {
|
||||
let buttonToggle: ButtonToggle;
|
||||
let destroyComp: DestroyComp;
|
||||
let buttonDir: MyButton;
|
||||
|
||||
class ButtonToggle {
|
||||
change = new EventEmitter();
|
||||
|
@ -22,7 +24,7 @@ describe('outputs', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: ButtonToggle,
|
||||
tag: 'button-toggle',
|
||||
selector: [[['button-toggle'], null]],
|
||||
template: function(ctx: any, cm: boolean) {},
|
||||
factory: () => buttonToggle = new ButtonToggle(),
|
||||
outputs: {change: 'change', resetStream: 'reset'}
|
||||
|
@ -36,16 +38,47 @@ describe('outputs', () => {
|
|||
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: OtherDir,
|
||||
selector: [[['', 'otherDir', ''], null]],
|
||||
factory: () => otherDir = new OtherDir,
|
||||
outputs: {changeStream: 'change'}
|
||||
});
|
||||
}
|
||||
|
||||
class DestroyComp {
|
||||
events: string[] = [];
|
||||
ngOnDestroy() { this.events.push('destroy'); }
|
||||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: DestroyComp,
|
||||
selector: [[['destroy-comp'], null]],
|
||||
template: function(ctx: any, cm: boolean) {},
|
||||
factory: () => destroyComp = new DestroyComp()
|
||||
});
|
||||
}
|
||||
|
||||
/** <button myButton (click)="onClick()">Click me</button> */
|
||||
class MyButton {
|
||||
click = new EventEmitter();
|
||||
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: MyButton,
|
||||
selector: [[['', 'myButton', ''], null]],
|
||||
factory: () => buttonDir = new MyButton,
|
||||
outputs: {click: 'click'}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const deps = [
|
||||
ButtonToggle.ngComponentDef, OtherDir.ngDirectiveDef, DestroyComp.ngComponentDef,
|
||||
MyButton.ngDirectiveDef
|
||||
];
|
||||
|
||||
it('should call component output function when event is emitted', () => {
|
||||
/** <button-toggle (change)="onChange()"></button-toggle> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, ButtonToggle);
|
||||
elementStart(0, 'button-toggle');
|
||||
{
|
||||
listener('change', function() { return ctx.onChange(); });
|
||||
}
|
||||
|
@ -55,7 +88,7 @@ describe('outputs', () => {
|
|||
|
||||
let counter = 0;
|
||||
const ctx = {onChange: () => counter++};
|
||||
renderToHtml(Template, ctx);
|
||||
renderToHtml(Template, ctx, deps);
|
||||
|
||||
buttonToggle !.change.next();
|
||||
expect(counter).toEqual(1);
|
||||
|
@ -68,7 +101,7 @@ describe('outputs', () => {
|
|||
/** <button-toggle (change)="onChange()" (reset)="onReset()"></button-toggle> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, ButtonToggle);
|
||||
elementStart(0, 'button-toggle');
|
||||
{
|
||||
listener('change', function() { return ctx.onChange(); });
|
||||
listener('reset', function() { return ctx.onReset(); });
|
||||
|
@ -80,7 +113,7 @@ describe('outputs', () => {
|
|||
let counter = 0;
|
||||
let resetCounter = 0;
|
||||
const ctx = {onChange: () => counter++, onReset: () => resetCounter++};
|
||||
renderToHtml(Template, ctx);
|
||||
renderToHtml(Template, ctx, deps);
|
||||
|
||||
buttonToggle !.change.next();
|
||||
expect(counter).toEqual(1);
|
||||
|
@ -93,7 +126,7 @@ describe('outputs', () => {
|
|||
/** <button-toggle (change)="counter++"></button-toggle> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, ButtonToggle);
|
||||
elementStart(0, 'button-toggle');
|
||||
{
|
||||
listener('change', function() { return ctx.counter++; });
|
||||
}
|
||||
|
@ -102,7 +135,7 @@ describe('outputs', () => {
|
|||
}
|
||||
|
||||
const ctx = {counter: 0};
|
||||
renderToHtml(Template, ctx);
|
||||
renderToHtml(Template, ctx, deps);
|
||||
|
||||
buttonToggle !.change.next();
|
||||
expect(ctx.counter).toEqual(1);
|
||||
|
@ -127,7 +160,7 @@ describe('outputs', () => {
|
|||
{
|
||||
if (ctx.condition) {
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, ButtonToggle);
|
||||
elementStart(0, 'button-toggle');
|
||||
{
|
||||
listener('change', function() { return ctx.onChange(); });
|
||||
}
|
||||
|
@ -141,13 +174,13 @@ describe('outputs', () => {
|
|||
|
||||
let counter = 0;
|
||||
const ctx = {onChange: () => counter++, condition: true};
|
||||
renderToHtml(Template, ctx);
|
||||
renderToHtml(Template, ctx, deps);
|
||||
|
||||
buttonToggle !.change.next();
|
||||
expect(counter).toEqual(1);
|
||||
|
||||
ctx.condition = false;
|
||||
renderToHtml(Template, ctx);
|
||||
renderToHtml(Template, ctx, deps);
|
||||
|
||||
buttonToggle !.change.next();
|
||||
expect(counter).toEqual(1);
|
||||
|
@ -177,7 +210,7 @@ describe('outputs', () => {
|
|||
{
|
||||
if (ctx.condition2) {
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, ButtonToggle);
|
||||
elementStart(0, 'button-toggle');
|
||||
{
|
||||
listener('change', function() { return ctx.onChange(); });
|
||||
}
|
||||
|
@ -195,33 +228,19 @@ describe('outputs', () => {
|
|||
|
||||
let counter = 0;
|
||||
const ctx = {onChange: () => counter++, condition: true, condition2: true};
|
||||
renderToHtml(Template, ctx);
|
||||
renderToHtml(Template, ctx, deps);
|
||||
|
||||
buttonToggle !.change.next();
|
||||
expect(counter).toEqual(1);
|
||||
|
||||
ctx.condition = false;
|
||||
renderToHtml(Template, ctx);
|
||||
renderToHtml(Template, ctx, deps);
|
||||
|
||||
buttonToggle !.change.next();
|
||||
expect(counter).toEqual(1);
|
||||
});
|
||||
|
||||
it('should work properly when view also has listeners and destroys', () => {
|
||||
let destroyComp: DestroyComp;
|
||||
|
||||
class DestroyComp {
|
||||
events: string[] = [];
|
||||
ngOnDestroy() { this.events.push('destroy'); }
|
||||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: DestroyComp,
|
||||
tag: 'destroy-comp',
|
||||
template: function(ctx: any, cm: boolean) {},
|
||||
factory: () => destroyComp = new DestroyComp()
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* % if (condition) {
|
||||
* <button (click)="onClick()">Click me</button>
|
||||
|
@ -243,12 +262,12 @@ describe('outputs', () => {
|
|||
text(1, 'Click me');
|
||||
}
|
||||
elementEnd();
|
||||
elementStart(2, ButtonToggle);
|
||||
elementStart(2, 'button-toggle');
|
||||
{
|
||||
listener('change', function() { return ctx.onChange(); });
|
||||
}
|
||||
elementEnd();
|
||||
elementStart(3, DestroyComp);
|
||||
elementStart(3, 'destroy-comp');
|
||||
elementEnd();
|
||||
}
|
||||
embeddedViewEnd();
|
||||
|
@ -260,7 +279,7 @@ describe('outputs', () => {
|
|||
let clickCounter = 0;
|
||||
let changeCounter = 0;
|
||||
const ctx = {condition: true, onChange: () => changeCounter++, onClick: () => clickCounter++};
|
||||
renderToHtml(Template, ctx);
|
||||
renderToHtml(Template, ctx, deps);
|
||||
|
||||
buttonToggle !.change.next();
|
||||
expect(changeCounter).toEqual(1);
|
||||
|
@ -272,7 +291,7 @@ describe('outputs', () => {
|
|||
expect(clickCounter).toEqual(1);
|
||||
|
||||
ctx.condition = false;
|
||||
renderToHtml(Template, ctx);
|
||||
renderToHtml(Template, ctx, deps);
|
||||
|
||||
expect(destroyComp !.events).toEqual(['destroy']);
|
||||
|
||||
|
@ -283,19 +302,9 @@ describe('outputs', () => {
|
|||
});
|
||||
|
||||
it('should fire event listeners along with outputs if they match', () => {
|
||||
let buttonDir: MyButton;
|
||||
|
||||
/** <button myButton (click)="onClick()">Click me</button> */
|
||||
class MyButton {
|
||||
click = new EventEmitter();
|
||||
|
||||
static ngDirectiveDef = defineDirective(
|
||||
{type: MyButton, factory: () => buttonDir = new MyButton, outputs: {click: 'click'}});
|
||||
}
|
||||
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'button', null, [MyButton]);
|
||||
elementStart(0, 'button', ['myButton', '']);
|
||||
{
|
||||
listener('click', function() { return ctx.onClick(); });
|
||||
}
|
||||
|
@ -304,7 +313,7 @@ describe('outputs', () => {
|
|||
}
|
||||
|
||||
let counter = 0;
|
||||
renderToHtml(Template, {counter, onClick: () => counter++});
|
||||
renderToHtml(Template, {counter, onClick: () => counter++}, deps);
|
||||
|
||||
// To match current Angular behavior, the click listener is still
|
||||
// set up in addition to any matching outputs.
|
||||
|
@ -320,7 +329,7 @@ describe('outputs', () => {
|
|||
/** <button-toggle (change)="onChange()" otherDir></button-toggle> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, ButtonToggle, null, [OtherDir]);
|
||||
elementStart(0, 'button-toggle', ['otherDir', '']);
|
||||
{
|
||||
listener('change', function() { return ctx.onChange(); });
|
||||
}
|
||||
|
@ -329,7 +338,7 @@ describe('outputs', () => {
|
|||
}
|
||||
|
||||
let counter = 0;
|
||||
renderToHtml(Template, {counter, onChange: () => counter++});
|
||||
renderToHtml(Template, {counter, onChange: () => counter++}, deps);
|
||||
|
||||
buttonToggle !.change.next();
|
||||
expect(counter).toEqual(1);
|
||||
|
@ -339,19 +348,23 @@ describe('outputs', () => {
|
|||
});
|
||||
|
||||
it('should work with an input and output of the same name', () => {
|
||||
let otherDir: OtherDir;
|
||||
let otherDir: OtherChangeDir;
|
||||
|
||||
class OtherDir {
|
||||
class OtherChangeDir {
|
||||
change: boolean;
|
||||
|
||||
static ngDirectiveDef = defineDirective(
|
||||
{type: OtherDir, factory: () => otherDir = new OtherDir, inputs: {change: 'change'}});
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: OtherChangeDir,
|
||||
selector: [[['', 'otherChangeDir', ''], null]],
|
||||
factory: () => otherDir = new OtherChangeDir,
|
||||
inputs: {change: 'change'}
|
||||
});
|
||||
}
|
||||
|
||||
/** <button-toggle (change)="onChange()" otherDir [change]="change"></button-toggle> */
|
||||
/** <button-toggle (change)="onChange()" otherChangeDir [change]="change"></button-toggle> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, ButtonToggle, null, [OtherDir]);
|
||||
elementStart(0, 'button-toggle', ['otherChangeDir', '']);
|
||||
{
|
||||
listener('change', function() { return ctx.onChange(); });
|
||||
}
|
||||
|
@ -361,10 +374,11 @@ describe('outputs', () => {
|
|||
}
|
||||
|
||||
let counter = 0;
|
||||
renderToHtml(Template, {counter, onChange: () => counter++, change: true});
|
||||
const deps = [ButtonToggle.ngComponentDef, OtherChangeDir.ngDirectiveDef];
|
||||
renderToHtml(Template, {counter, onChange: () => counter++, change: true}, deps);
|
||||
expect(otherDir !.change).toEqual(true);
|
||||
|
||||
renderToHtml(Template, {counter, onChange: () => counter++, change: false});
|
||||
renderToHtml(Template, {counter, onChange: () => counter++, change: false}, deps);
|
||||
expect(otherDir !.change).toEqual(false);
|
||||
|
||||
buttonToggle !.change.next();
|
||||
|
@ -395,7 +409,7 @@ describe('outputs', () => {
|
|||
{
|
||||
if (ctx.condition) {
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, ButtonToggle);
|
||||
elementStart(0, 'button-toggle');
|
||||
{
|
||||
listener('change', function() { return ctx.onChange(); });
|
||||
}
|
||||
|
@ -404,7 +418,7 @@ describe('outputs', () => {
|
|||
embeddedViewEnd();
|
||||
} else {
|
||||
if (embeddedViewStart(1)) {
|
||||
elementStart(0, 'div', null, [OtherDir]);
|
||||
elementStart(0, 'div', ['otherDir', '']);
|
||||
{
|
||||
listener('change', function() { return ctx.onChange(); });
|
||||
}
|
||||
|
@ -418,13 +432,13 @@ describe('outputs', () => {
|
|||
|
||||
let counter = 0;
|
||||
const ctx = {condition: true, onChange: () => counter++, onClick: () => {}};
|
||||
renderToHtml(Template, ctx);
|
||||
renderToHtml(Template, ctx, deps);
|
||||
|
||||
buttonToggle !.change.next();
|
||||
expect(counter).toEqual(1);
|
||||
|
||||
ctx.condition = false;
|
||||
renderToHtml(Template, ctx);
|
||||
renderToHtml(Template, ctx, deps);
|
||||
expect(counter).toEqual(1);
|
||||
|
||||
otherDir !.changeStream.next();
|
||||
|
|
|
@ -6,15 +6,15 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Directive, OnChanges, OnDestroy, Pipe, PipeTransform, SimpleChange, SimpleChanges, WrappedValue} from '@angular/core';
|
||||
import {Directive, OnChanges, OnDestroy, Pipe, PipeTransform} from '@angular/core';
|
||||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||
|
||||
import {NgOnChangesFeature, defineComponent, defineDirective, definePipe} from '../../src/render3/definition';
|
||||
import {defineDirective, definePipe} from '../../src/render3/definition';
|
||||
import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, load, loadDirective, text, textBinding} from '../../src/render3/instructions';
|
||||
import {pipe, pipeBind1, pipeBind3, pipeBind4, pipeBindV} from '../../src/render3/pipe';
|
||||
|
||||
import {RenderLog, getRendererFactory2, patchLoggingRenderer2} from './imported_renderer2';
|
||||
import {renderComponent, renderToHtml} from './render_util';
|
||||
import {renderToHtml} from './render_util';
|
||||
|
||||
|
||||
let log: string[] = [];
|
||||
|
@ -51,8 +51,12 @@ describe('pipe', () => {
|
|||
|
||||
constructor() { this.dirProp = ''; }
|
||||
|
||||
static ngDirectiveDef =
|
||||
defineDirective({type: MyDir, factory: () => new MyDir(), inputs: {dirProp: 'elprop'}});
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: MyDir,
|
||||
selector: [[['', 'myDir', ''], null]],
|
||||
factory: () => new MyDir(),
|
||||
inputs: {dirProp: 'elprop'}
|
||||
});
|
||||
}
|
||||
|
||||
@Pipe({name: 'double'})
|
||||
|
@ -67,14 +71,14 @@ describe('pipe', () => {
|
|||
|
||||
function Template(ctx: string, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', null, [MyDir]);
|
||||
elementStart(0, 'div', ['myDir', '']);
|
||||
pipe(1, DoublePipe.ngPipeDef);
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'elprop', bind(pipeBind1(1, ctx)));
|
||||
directive = loadDirective(0);
|
||||
}
|
||||
renderToHtml(Template, 'a');
|
||||
renderToHtml(Template, 'a', [MyDir.ngDirectiveDef]);
|
||||
expect(directive !.dirProp).toEqual('aa');
|
||||
});
|
||||
|
||||
|
@ -124,11 +128,11 @@ describe('pipe', () => {
|
|||
}
|
||||
elementProperty(0, 'someProp', bind(pipeBind1(1, 'Megatron')));
|
||||
}
|
||||
renderToHtml(Template, person, rendererFactory2);
|
||||
renderToHtml(Template, person, [], rendererFactory2);
|
||||
expect(renderLog.log).toEqual(['someProp=Megatron']);
|
||||
|
||||
renderLog.clear();
|
||||
renderToHtml(Template, person, rendererFactory2);
|
||||
renderToHtml(Template, person, [], rendererFactory2);
|
||||
expect(renderLog.log).toEqual([]);
|
||||
});
|
||||
|
||||
|
@ -192,7 +196,7 @@ describe('pipe', () => {
|
|||
containerRefreshEnd();
|
||||
}
|
||||
const pipeInstances: CountingPipe[] = [];
|
||||
renderToHtml(Template, {}, rendererFactory2);
|
||||
renderToHtml(Template, {}, [], rendererFactory2);
|
||||
expect(pipeInstances.length).toEqual(4);
|
||||
expect(pipeInstances[0]).toBeAnInstanceOf(CountingPipe);
|
||||
expect(pipeInstances[1]).toBe(pipeInstances[0]);
|
||||
|
@ -249,7 +253,7 @@ describe('pipe', () => {
|
|||
containerRefreshEnd();
|
||||
}
|
||||
const pipeInstances: CountingImpurePipe[] = [];
|
||||
renderToHtml(Template, {}, rendererFactory2);
|
||||
renderToHtml(Template, {}, [], rendererFactory2);
|
||||
expect(pipeInstances.length).toEqual(4);
|
||||
expect(pipeInstances[0]).toBeAnInstanceOf(CountingImpurePipe);
|
||||
expect(pipeInstances[1]).toBeAnInstanceOf(CountingImpurePipe);
|
||||
|
|
|
@ -11,7 +11,7 @@ import {EventEmitter} from '@angular/core';
|
|||
import {defineComponent, defineDirective, tick} from '../../src/render3/index';
|
||||
import {NO_CHANGE, bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, listener, loadDirective, text, textBinding} from '../../src/render3/instructions';
|
||||
|
||||
import {ComponentFixture, renderToHtml} from './render_util';
|
||||
import {ComponentFixture, TemplateFixture, createComponent, renderToHtml} from './render_util';
|
||||
|
||||
describe('elementProperty', () => {
|
||||
|
||||
|
@ -68,7 +68,7 @@ describe('elementProperty', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: HostBindingComp,
|
||||
tag: 'host-binding-comp',
|
||||
selector: [[['host-binding-comp'], null]],
|
||||
factory: () => new HostBindingComp(),
|
||||
hostBindings: (dirIndex: number, elIndex: number) => {
|
||||
const instance = loadDirective(dirIndex) as HostBindingComp;
|
||||
|
@ -89,12 +89,18 @@ describe('elementProperty', () => {
|
|||
describe('input properties', () => {
|
||||
let button: MyButton;
|
||||
let otherDir: OtherDir;
|
||||
let otherDisabledDir: OtherDisabledDir;
|
||||
let idDir: IdDir;
|
||||
|
||||
class MyButton {
|
||||
disabled: boolean;
|
||||
|
||||
static ngDirectiveDef = defineDirective(
|
||||
{type: MyButton, factory: () => button = new MyButton(), inputs: {disabled: 'disabled'}});
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: MyButton,
|
||||
selector: [[['', 'myButton', ''], null]],
|
||||
factory: () => button = new MyButton(),
|
||||
inputs: {disabled: 'disabled'}
|
||||
});
|
||||
}
|
||||
|
||||
class OtherDir {
|
||||
|
@ -103,18 +109,47 @@ describe('elementProperty', () => {
|
|||
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: OtherDir,
|
||||
selector: [[['', 'otherDir', ''], null]],
|
||||
factory: () => otherDir = new OtherDir(),
|
||||
inputs: {id: 'id'},
|
||||
outputs: {clickStream: 'click'}
|
||||
});
|
||||
}
|
||||
|
||||
class OtherDisabledDir {
|
||||
disabled: boolean;
|
||||
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: OtherDisabledDir,
|
||||
selector: [[['', 'otherDisabledDir', ''], null]],
|
||||
factory: () => otherDisabledDir = new OtherDisabledDir(),
|
||||
inputs: {disabled: 'disabled'}
|
||||
});
|
||||
}
|
||||
|
||||
class IdDir {
|
||||
idNumber: number;
|
||||
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: IdDir,
|
||||
selector: [[['', 'idDir', ''], null]],
|
||||
factory: () => idDir = new IdDir(),
|
||||
inputs: {idNumber: 'id'}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const deps = [
|
||||
MyButton.ngDirectiveDef, OtherDir.ngDirectiveDef, OtherDisabledDir.ngDirectiveDef,
|
||||
IdDir.ngDirectiveDef
|
||||
];
|
||||
|
||||
it('should check input properties before setting (directives)', () => {
|
||||
|
||||
/** <button myButton [id]="id" [disabled]="isDisabled">Click me</button> */
|
||||
/** <button myButton otherDir [id]="id" [disabled]="isDisabled">Click me</button> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'button', null, [MyButton, OtherDir]);
|
||||
elementStart(0, 'button', ['otherDir', '', 'myButton', '']);
|
||||
{ text(1, 'Click me'); }
|
||||
elementEnd();
|
||||
}
|
||||
|
@ -124,13 +159,15 @@ describe('elementProperty', () => {
|
|||
}
|
||||
|
||||
const ctx: any = {isDisabled: true, id: 0};
|
||||
expect(renderToHtml(Template, ctx)).toEqual(`<button>Click me</button>`);
|
||||
expect(renderToHtml(Template, ctx, deps))
|
||||
.toEqual(`<button mybutton="" otherdir="">Click me</button>`);
|
||||
expect(button !.disabled).toEqual(true);
|
||||
expect(otherDir !.id).toEqual(0);
|
||||
|
||||
ctx.isDisabled = false;
|
||||
ctx.id = 1;
|
||||
expect(renderToHtml(Template, ctx)).toEqual(`<button>Click me</button>`);
|
||||
expect(renderToHtml(Template, ctx, deps))
|
||||
.toEqual(`<button mybutton="" otherdir="">Click me</button>`);
|
||||
expect(button !.disabled).toEqual(false);
|
||||
expect(otherDir !.id).toEqual(1);
|
||||
});
|
||||
|
@ -140,7 +177,7 @@ describe('elementProperty', () => {
|
|||
/** <button myButton [id]="id" [disabled]="isDisabled">Click me</button> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'button', null, [MyButton]);
|
||||
elementStart(0, 'button', ['myButton', '']);
|
||||
{ text(1, 'Click me'); }
|
||||
elementEnd();
|
||||
}
|
||||
|
@ -150,23 +187,27 @@ describe('elementProperty', () => {
|
|||
}
|
||||
|
||||
const ctx: any = {isDisabled: true, id: 0};
|
||||
expect(renderToHtml(Template, ctx)).toEqual(`<button id="0">Click me</button>`);
|
||||
|
||||
expect(renderToHtml(Template, ctx, deps))
|
||||
.toEqual(`<button id="0" mybutton="">Click me</button>`);
|
||||
expect(button !.disabled).toEqual(true);
|
||||
|
||||
ctx.isDisabled = false;
|
||||
ctx.id = 1;
|
||||
expect(renderToHtml(Template, ctx)).toEqual(`<button id="1">Click me</button>`);
|
||||
expect(renderToHtml(Template, ctx, deps))
|
||||
.toEqual(`<button id="1" mybutton="">Click me</button>`);
|
||||
expect(button !.disabled).toEqual(false);
|
||||
});
|
||||
|
||||
it('should check that property is not an input property before setting (component)', () => {
|
||||
let comp: Comp;
|
||||
|
||||
class Comp {
|
||||
id: number;
|
||||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: Comp,
|
||||
tag: 'comp',
|
||||
selector: [[['comp'], null]],
|
||||
template: function(ctx: any, cm: boolean) {},
|
||||
factory: () => comp = new Comp(),
|
||||
inputs: {id: 'id'}
|
||||
|
@ -176,36 +217,26 @@ describe('elementProperty', () => {
|
|||
/** <comp [id]="id"></comp> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, Comp);
|
||||
elementStart(0, 'comp');
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'id', bind(ctx.id));
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {id: 1})).toEqual(`<comp></comp>`);
|
||||
const deps = [Comp.ngComponentDef];
|
||||
expect(renderToHtml(Template, {id: 1}, deps)).toEqual(`<comp></comp>`);
|
||||
expect(comp !.id).toEqual(1);
|
||||
|
||||
expect(renderToHtml(Template, {id: 2})).toEqual(`<comp></comp>`);
|
||||
expect(renderToHtml(Template, {id: 2}, deps)).toEqual(`<comp></comp>`);
|
||||
expect(comp !.id).toEqual(2);
|
||||
});
|
||||
|
||||
it('should support two input properties with the same name', () => {
|
||||
let otherDisabledDir: OtherDisabledDir;
|
||||
|
||||
class OtherDisabledDir {
|
||||
disabled: boolean;
|
||||
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: OtherDisabledDir,
|
||||
factory: () => otherDisabledDir = new OtherDisabledDir(),
|
||||
inputs: {disabled: 'disabled'}
|
||||
});
|
||||
}
|
||||
|
||||
/** <button myButton otherDisabledDir [disabled]="isDisabled">Click me</button> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'button', null, [MyButton, OtherDisabledDir]);
|
||||
elementStart(0, 'button', ['myButton', '', 'otherDisabledDir', '']);
|
||||
{ text(1, 'Click me'); }
|
||||
elementEnd();
|
||||
}
|
||||
|
@ -213,12 +244,14 @@ describe('elementProperty', () => {
|
|||
}
|
||||
|
||||
const ctx: any = {isDisabled: true};
|
||||
expect(renderToHtml(Template, ctx)).toEqual(`<button>Click me</button>`);
|
||||
expect(renderToHtml(Template, ctx, deps))
|
||||
.toEqual(`<button mybutton="" otherdisableddir="">Click me</button>`);
|
||||
expect(button !.disabled).toEqual(true);
|
||||
expect(otherDisabledDir !.disabled).toEqual(true);
|
||||
|
||||
ctx.isDisabled = false;
|
||||
expect(renderToHtml(Template, ctx)).toEqual(`<button>Click me</button>`);
|
||||
expect(renderToHtml(Template, ctx, deps))
|
||||
.toEqual(`<button mybutton="" otherdisableddir="">Click me</button>`);
|
||||
expect(button !.disabled).toEqual(false);
|
||||
expect(otherDisabledDir !.disabled).toEqual(false);
|
||||
});
|
||||
|
@ -227,7 +260,7 @@ describe('elementProperty', () => {
|
|||
/** <button otherDir [id]="id" (click)="onClick()">Click me</button> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'button', null, [OtherDir]);
|
||||
elementStart(0, 'button', ['otherDir', '']);
|
||||
{
|
||||
listener('click', ctx.onClick.bind(ctx));
|
||||
text(1, 'Click me');
|
||||
|
@ -239,27 +272,18 @@ describe('elementProperty', () => {
|
|||
|
||||
let counter = 0;
|
||||
const ctx: any = {id: 1, onClick: () => counter++};
|
||||
expect(renderToHtml(Template, ctx)).toEqual(`<button>Click me</button>`);
|
||||
expect(renderToHtml(Template, ctx, deps)).toEqual(`<button otherdir="">Click me</button>`);
|
||||
expect(otherDir !.id).toEqual(1);
|
||||
|
||||
otherDir !.clickStream.next();
|
||||
expect(counter).toEqual(1);
|
||||
|
||||
ctx.id = 2;
|
||||
renderToHtml(Template, ctx);
|
||||
renderToHtml(Template, ctx, deps);
|
||||
expect(otherDir !.id).toEqual(2);
|
||||
});
|
||||
|
||||
it('should support unrelated element properties at same index in if-else block', () => {
|
||||
let idDir: IdDir;
|
||||
|
||||
class IdDir {
|
||||
idNumber: number;
|
||||
|
||||
static ngDirectiveDef = defineDirective(
|
||||
{type: IdDir, factory: () => idDir = new IdDir(), inputs: {idNumber: 'id'}});
|
||||
}
|
||||
|
||||
/**
|
||||
* <button idDir [id]="id1">Click me</button> // inputs: {'id': [0, 'idNumber']}
|
||||
* % if (condition) {
|
||||
|
@ -270,7 +294,7 @@ describe('elementProperty', () => {
|
|||
*/
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'button', null, [IdDir]);
|
||||
elementStart(0, 'button', ['idDir', '']);
|
||||
{ text(1, 'Click me'); }
|
||||
elementEnd();
|
||||
container(2);
|
||||
|
@ -288,7 +312,7 @@ describe('elementProperty', () => {
|
|||
embeddedViewEnd();
|
||||
} else {
|
||||
if (embeddedViewStart(1)) {
|
||||
elementStart(0, 'button', null, [OtherDir]);
|
||||
elementStart(0, 'button', ['otherDir', '']);
|
||||
{ text(1, 'Click me too'); }
|
||||
elementEnd();
|
||||
}
|
||||
|
@ -299,12 +323,13 @@ describe('elementProperty', () => {
|
|||
containerRefreshEnd();
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {condition: true, id1: 'one', id2: 'two', id3: 'three'}))
|
||||
.toEqual(`<button>Click me</button><button id="two">Click me too</button>`);
|
||||
expect(renderToHtml(Template, {condition: true, id1: 'one', id2: 'two', id3: 'three'}, deps))
|
||||
.toEqual(`<button iddir="">Click me</button><button id="two">Click me too</button>`);
|
||||
expect(idDir !.idNumber).toEqual('one');
|
||||
|
||||
expect(renderToHtml(Template, {condition: false, id1: 'four', id2: 'two', id3: 'three'}))
|
||||
.toEqual(`<button>Click me</button><button>Click me too</button>`);
|
||||
expect(
|
||||
renderToHtml(Template, {condition: false, id1: 'four', id2: 'two', id3: 'three'}, deps))
|
||||
.toEqual(`<button iddir="">Click me</button><button otherdir="">Click me too</button>`);
|
||||
expect(idDir !.idNumber).toEqual('four');
|
||||
expect(otherDir !.id).toEqual('three');
|
||||
});
|
||||
|
@ -320,6 +345,7 @@ describe('elementProperty', () => {
|
|||
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: MyDir,
|
||||
selector: [[['', 'myDir', ''], null]],
|
||||
factory: () => myDir = new MyDir(),
|
||||
inputs: {role: 'role', direction: 'dir'},
|
||||
outputs: {changeStream: 'change'},
|
||||
|
@ -331,21 +357,27 @@ describe('elementProperty', () => {
|
|||
class MyDirB {
|
||||
roleB: string;
|
||||
|
||||
static ngDirectiveDef = defineDirective(
|
||||
{type: MyDirB, factory: () => dirB = new MyDirB(), inputs: {roleB: 'role'}});
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: MyDirB,
|
||||
selector: [[['', 'myDirB', ''], null]],
|
||||
factory: () => dirB = new MyDirB(),
|
||||
inputs: {roleB: 'role'}
|
||||
});
|
||||
}
|
||||
|
||||
const deps = [MyDir.ngDirectiveDef, MyDirB.ngDirectiveDef];
|
||||
|
||||
it('should set input property based on attribute if existing', () => {
|
||||
|
||||
/** <div role="button" myDir></div> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', ['role', 'button'], [MyDir]);
|
||||
elementStart(0, 'div', ['role', 'button', 'myDir', '']);
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {})).toEqual(`<div role="button"></div>`);
|
||||
expect(renderToHtml(Template, {}, deps)).toEqual(`<div mydir="" role="button"></div>`);
|
||||
expect(myDir !.role).toEqual('button');
|
||||
});
|
||||
|
||||
|
@ -354,16 +386,17 @@ describe('elementProperty', () => {
|
|||
/** <div role="button" [role]="role" myDir></div> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', ['role', 'button'], [MyDir]);
|
||||
elementStart(0, 'div', ['role', 'button', 'myDir', '']);
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'role', bind(ctx.role));
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {role: 'listbox'})).toEqual(`<div role="button"></div>`);
|
||||
expect(renderToHtml(Template, {role: 'listbox'}, deps))
|
||||
.toEqual(`<div mydir="" role="button"></div>`);
|
||||
expect(myDir !.role).toEqual('listbox');
|
||||
|
||||
renderToHtml(Template, {role: 'button'});
|
||||
renderToHtml(Template, {role: 'button'}, deps);
|
||||
expect(myDir !.role).toEqual('button');
|
||||
});
|
||||
|
||||
|
@ -372,12 +405,13 @@ describe('elementProperty', () => {
|
|||
/** <div role="button" myDir myDirB></div> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', ['role', 'button'], [MyDir, MyDirB]);
|
||||
elementStart(0, 'div', ['role', 'button', 'myDir', '', 'myDirB', '']);
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {})).toEqual(`<div role="button"></div>`);
|
||||
expect(renderToHtml(Template, {}, deps))
|
||||
.toEqual(`<div mydir="" mydirb="" role="button"></div>`);
|
||||
expect(myDir !.role).toEqual('button');
|
||||
expect(dirB !.roleB).toEqual('button');
|
||||
});
|
||||
|
@ -387,12 +421,13 @@ describe('elementProperty', () => {
|
|||
/** <div role="button" dir="rtl" myDir></div> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', ['role', 'button', 'dir', 'rtl'], [MyDir]);
|
||||
elementStart(0, 'div', ['role', 'button', 'dir', 'rtl', 'myDir', '']);
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {})).toEqual(`<div dir="rtl" role="button"></div>`);
|
||||
expect(renderToHtml(Template, {}, deps))
|
||||
.toEqual(`<div dir="rtl" mydir="" role="button"></div>`);
|
||||
expect(myDir !.role).toEqual('button');
|
||||
expect(myDir !.direction).toEqual('rtl');
|
||||
});
|
||||
|
@ -402,16 +437,15 @@ describe('elementProperty', () => {
|
|||
/** <div role="button" (change)="onChange()" myDir></div> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', ['role', 'button'], [MyDir]);
|
||||
elementStart(0, 'div', ['role', 'button', 'myDir', '']);
|
||||
{ listener('change', ctx.onChange.bind(ctx)); }
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
||||
let counter = 0;
|
||||
expect(renderToHtml(Template, {
|
||||
onChange: () => counter++
|
||||
})).toEqual(`<div role="button"></div>`);
|
||||
expect(renderToHtml(Template, {onChange: () => counter++}, deps))
|
||||
.toEqual(`<div mydir="" role="button"></div>`);
|
||||
expect(myDir !.role).toEqual('button');
|
||||
|
||||
myDir !.changeStream.next();
|
||||
|
@ -426,15 +460,16 @@ describe('elementProperty', () => {
|
|||
*/
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', ['role', 'button', 'dir', 'rtl'], [MyDir]);
|
||||
elementStart(0, 'div', ['role', 'button', 'dir', 'rtl', 'myDir', '']);
|
||||
elementEnd();
|
||||
elementStart(1, 'div', ['role', 'listbox'], [MyDirB]);
|
||||
elementStart(1, 'div', ['role', 'listbox', 'myDirB', '']);
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {}))
|
||||
.toEqual(`<div dir="rtl" role="button"></div><div role="listbox"></div>`);
|
||||
expect(renderToHtml(Template, {}, deps))
|
||||
.toEqual(
|
||||
`<div dir="rtl" mydir="" role="button"></div><div mydirb="" role="listbox"></div>`);
|
||||
expect(myDir !.role).toEqual('button');
|
||||
expect(myDir !.direction).toEqual('rtl');
|
||||
expect(dirB !.roleB).toEqual('listbox');
|
||||
|
@ -452,7 +487,7 @@ describe('elementProperty', () => {
|
|||
*/
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', ['role', 'listbox'], [MyDir]);
|
||||
elementStart(0, 'div', ['role', 'listbox', 'myDir', '']);
|
||||
elementEnd();
|
||||
container(1);
|
||||
}
|
||||
|
@ -460,7 +495,7 @@ describe('elementProperty', () => {
|
|||
{
|
||||
if (ctx.condition) {
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, 'div', ['role', 'button'], [MyDirB]);
|
||||
elementStart(0, 'div', ['role', 'button', 'myDirB', '']);
|
||||
elementEnd();
|
||||
}
|
||||
embeddedViewEnd();
|
||||
|
@ -476,16 +511,14 @@ describe('elementProperty', () => {
|
|||
containerRefreshEnd();
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {
|
||||
condition: true
|
||||
})).toEqual(`<div role="listbox"></div><div role="button"></div>`);
|
||||
expect(renderToHtml(Template, {condition: true}, deps))
|
||||
.toEqual(`<div mydir="" role="listbox"></div><div mydirb="" role="button"></div>`);
|
||||
expect(myDir !.role).toEqual('listbox');
|
||||
expect(dirB !.roleB).toEqual('button');
|
||||
expect((dirB !as any).role).toBeUndefined();
|
||||
|
||||
expect(renderToHtml(Template, {
|
||||
condition: false
|
||||
})).toEqual(`<div role="listbox"></div><div role="menu"></div>`);
|
||||
expect(renderToHtml(Template, {condition: false}, deps))
|
||||
.toEqual(`<div mydir="" role="listbox"></div><div role="menu"></div>`);
|
||||
expect(myDir !.role).toEqual('listbox');
|
||||
});
|
||||
|
||||
|
@ -494,18 +527,19 @@ describe('elementProperty', () => {
|
|||
class Comp {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: Comp,
|
||||
tag: 'comp',
|
||||
selector: [[['comp'], null]],
|
||||
/** <div role="button" dir #dir="myDir"></div> {{ dir.role }} */
|
||||
template: function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div', ['role', 'button'], [MyDir], ['dir', 'myDir']);
|
||||
elementStart(0, 'div', ['role', 'button', 'myDir', ''], ['dir', 'myDir']);
|
||||
elementEnd();
|
||||
text(1);
|
||||
}
|
||||
// TODO: remove this loadDirective when removing MyDir
|
||||
textBinding(1, bind(loadDirective<MyDir>(0).role));
|
||||
},
|
||||
factory: () => new Comp()
|
||||
factory: () => new Comp(),
|
||||
directiveDefs: () => [MyDir.ngDirectiveDef]
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -522,7 +556,7 @@ describe('elementProperty', () => {
|
|||
{
|
||||
for (let i = 0; i < 2; i++) {
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, Comp);
|
||||
elementStart(0, 'comp');
|
||||
elementEnd();
|
||||
}
|
||||
embeddedViewEnd();
|
||||
|
@ -531,9 +565,9 @@ describe('elementProperty', () => {
|
|||
containerRefreshEnd();
|
||||
}
|
||||
|
||||
expect(renderToHtml(Template, {}))
|
||||
expect(renderToHtml(Template, {}, [Comp.ngComponentDef]))
|
||||
.toEqual(
|
||||
`<comp><div role="button"></div>button</comp><comp><div role="button"></div>button</comp>`);
|
||||
`<comp><div mydir="" role="button"></div>button</comp><comp><div mydir="" role="button"></div>button</comp>`);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -18,34 +18,36 @@ describe('array literals', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: MyComp,
|
||||
tag: 'my-comp',
|
||||
selector: [[['my-comp'], null]],
|
||||
factory: function MyComp_Factory() { return myComp = new MyComp(); },
|
||||
template: function MyComp_Template(ctx: MyComp, cm: boolean) {},
|
||||
inputs: {names: 'names'}
|
||||
});
|
||||
}
|
||||
|
||||
const defs = [MyComp.ngComponentDef];
|
||||
|
||||
it('should support an array literal with a binding', () => {
|
||||
const e0_ff = (v: any) => ['Nancy', v, 'Bess'];
|
||||
|
||||
/** <my-comp [names]="['Nancy', customName, 'Bess']"></my-comp> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, MyComp);
|
||||
elementStart(0, 'my-comp');
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'names', bind(pureFunction1(e0_ff, ctx.customName)));
|
||||
}
|
||||
|
||||
renderToHtml(Template, {customName: 'Carson'});
|
||||
renderToHtml(Template, {customName: 'Carson'}, defs);
|
||||
const firstArray = myComp !.names;
|
||||
expect(firstArray).toEqual(['Nancy', 'Carson', 'Bess']);
|
||||
|
||||
renderToHtml(Template, {customName: 'Carson'});
|
||||
renderToHtml(Template, {customName: 'Carson'}, defs);
|
||||
expect(myComp !.names).toEqual(['Nancy', 'Carson', 'Bess']);
|
||||
expect(firstArray).toBe(myComp !.names);
|
||||
|
||||
renderToHtml(Template, {customName: 'Hannah'});
|
||||
renderToHtml(Template, {customName: 'Hannah'}, defs);
|
||||
expect(myComp !.names).toEqual(['Nancy', 'Hannah', 'Bess']);
|
||||
|
||||
// Identity must change if binding changes
|
||||
|
@ -54,7 +56,7 @@ describe('array literals', () => {
|
|||
// The property should not be set if the exp value is the same, so artificially
|
||||
// setting the property to ensure it's not overwritten.
|
||||
myComp !.names = ['should not be overwritten'];
|
||||
renderToHtml(Template, {customName: 'Hannah'});
|
||||
renderToHtml(Template, {customName: 'Hannah'}, defs);
|
||||
expect(myComp !.names).toEqual(['should not be overwritten']);
|
||||
});
|
||||
|
||||
|
@ -67,7 +69,7 @@ describe('array literals', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: ManyPropComp,
|
||||
tag: 'many-prop-comp',
|
||||
selector: [[['many-prop-comp'], null]],
|
||||
factory: function ManyPropComp_Factory() { return manyPropComp = new ManyPropComp(); },
|
||||
template: function ManyPropComp_Template(ctx: ManyPropComp, cm: boolean) {},
|
||||
inputs: {names1: 'names1', names2: 'names2'}
|
||||
|
@ -83,18 +85,19 @@ describe('array literals', () => {
|
|||
*/
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, ManyPropComp);
|
||||
elementStart(0, 'many-prop-comp');
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'names1', bind(pureFunction1(e0_ff, ctx.customName)));
|
||||
elementProperty(0, 'names2', bind(pureFunction1(e0_ff_1, ctx.customName2)));
|
||||
}
|
||||
|
||||
renderToHtml(Template, {customName: 'Carson', customName2: 'George'});
|
||||
const defs = [ManyPropComp.ngComponentDef];
|
||||
renderToHtml(Template, {customName: 'Carson', customName2: 'George'}, defs);
|
||||
expect(manyPropComp !.names1).toEqual(['Nancy', 'Carson']);
|
||||
expect(manyPropComp !.names2).toEqual(['George']);
|
||||
|
||||
renderToHtml(Template, {customName: 'George', customName2: 'Carson'});
|
||||
renderToHtml(Template, {customName: 'George', customName2: 'Carson'}, defs);
|
||||
expect(manyPropComp !.names1).toEqual(['Nancy', 'George']);
|
||||
expect(manyPropComp !.names2).toEqual(['Carson']);
|
||||
});
|
||||
|
@ -115,36 +118,37 @@ describe('array literals', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: ParentComp,
|
||||
tag: 'parent-comp',
|
||||
selector: [[['parent-comp'], null]],
|
||||
factory: () => new ParentComp(),
|
||||
template: function(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, MyComp);
|
||||
elementStart(0, 'my-comp');
|
||||
myComps.push(loadDirective(0));
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'names', bind(ctx.someFn(pureFunction1(e0_ff, ctx.customName))));
|
||||
}
|
||||
},
|
||||
directiveDefs: defs
|
||||
});
|
||||
}
|
||||
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, ParentComp);
|
||||
elementStart(0, 'parent-comp');
|
||||
elementEnd();
|
||||
elementStart(1, ParentComp);
|
||||
elementStart(1, 'parent-comp');
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
||||
renderToHtml(Template, {});
|
||||
renderToHtml(Template, {}, [ParentComp.ngComponentDef]);
|
||||
const firstArray = myComps[0].names;
|
||||
const secondArray = myComps[1].names;
|
||||
expect(firstArray).toEqual(['NANCY', 'Bess']);
|
||||
expect(secondArray).toEqual(['NANCY', 'Bess']);
|
||||
expect(firstArray).not.toBe(secondArray);
|
||||
|
||||
renderToHtml(Template, {});
|
||||
renderToHtml(Template, {}, [ParentComp.ngComponentDef]);
|
||||
expect(firstArray).toEqual(['NANCY', 'Bess']);
|
||||
expect(secondArray).toEqual(['NANCY', 'Bess']);
|
||||
expect(firstArray).toBe(myComps[0].names);
|
||||
|
@ -157,31 +161,31 @@ describe('array literals', () => {
|
|||
/** <my-comp [names]="['Nancy', customName, 'Bess', customName2]"></my-comp> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, MyComp);
|
||||
elementStart(0, 'my-comp');
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'names', bind(pureFunction2(e0_ff, ctx.customName, ctx.customName2)));
|
||||
}
|
||||
|
||||
renderToHtml(Template, {customName: 'Carson', customName2: 'Hannah'});
|
||||
renderToHtml(Template, {customName: 'Carson', customName2: 'Hannah'}, defs);
|
||||
const firstArray = myComp !.names;
|
||||
expect(firstArray).toEqual(['Nancy', 'Carson', 'Bess', 'Hannah']);
|
||||
|
||||
renderToHtml(Template, {customName: 'Carson', customName2: 'Hannah'});
|
||||
renderToHtml(Template, {customName: 'Carson', customName2: 'Hannah'}, defs);
|
||||
expect(myComp !.names).toEqual(['Nancy', 'Carson', 'Bess', 'Hannah']);
|
||||
expect(firstArray).toBe(myComp !.names);
|
||||
|
||||
renderToHtml(Template, {customName: 'George', customName2: 'Hannah'});
|
||||
renderToHtml(Template, {customName: 'George', customName2: 'Hannah'}, defs);
|
||||
expect(myComp !.names).toEqual(['Nancy', 'George', 'Bess', 'Hannah']);
|
||||
expect(firstArray).not.toBe(myComp !.names);
|
||||
|
||||
renderToHtml(Template, {customName: 'Frank', customName2: 'Ned'});
|
||||
renderToHtml(Template, {customName: 'Frank', customName2: 'Ned'}, defs);
|
||||
expect(myComp !.names).toEqual(['Nancy', 'Frank', 'Bess', 'Ned']);
|
||||
|
||||
// The property should not be set if the exp value is the same, so artificially
|
||||
// setting the property to ensure it's not overwritten.
|
||||
myComp !.names = ['should not be overwritten'];
|
||||
renderToHtml(Template, {customName: 'Frank', customName2: 'Ned'});
|
||||
renderToHtml(Template, {customName: 'Frank', customName2: 'Ned'}, defs);
|
||||
expect(myComp !.names).toEqual(['should not be overwritten']);
|
||||
});
|
||||
|
||||
|
@ -210,22 +214,22 @@ describe('array literals', () => {
|
|||
|
||||
function Template(c: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, MyComp);
|
||||
elementStart(0, 'my-comp');
|
||||
f3Comp = loadDirective(0);
|
||||
elementEnd();
|
||||
elementStart(1, MyComp);
|
||||
elementStart(1, 'my-comp');
|
||||
f4Comp = loadDirective(1);
|
||||
elementEnd();
|
||||
elementStart(2, MyComp);
|
||||
elementStart(2, 'my-comp');
|
||||
f5Comp = loadDirective(2);
|
||||
elementEnd();
|
||||
elementStart(3, MyComp);
|
||||
elementStart(3, 'my-comp');
|
||||
f6Comp = loadDirective(3);
|
||||
elementEnd();
|
||||
elementStart(4, MyComp);
|
||||
elementStart(4, 'my-comp');
|
||||
f7Comp = loadDirective(4);
|
||||
elementEnd();
|
||||
elementStart(5, MyComp);
|
||||
elementStart(5, 'my-comp');
|
||||
f8Comp = loadDirective(5);
|
||||
elementEnd();
|
||||
}
|
||||
|
@ -239,7 +243,7 @@ describe('array literals', () => {
|
|||
5, 'names', bind(pureFunction8(e10_ff, c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7])));
|
||||
}
|
||||
|
||||
renderToHtml(Template, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']);
|
||||
renderToHtml(Template, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], defs);
|
||||
expect(f3Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
|
||||
expect(f4Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
|
||||
expect(f5Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
|
||||
|
@ -247,7 +251,7 @@ describe('array literals', () => {
|
|||
expect(f7Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
|
||||
expect(f8Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
|
||||
|
||||
renderToHtml(Template, ['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1', 'i1']);
|
||||
renderToHtml(Template, ['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1', 'i1'], defs);
|
||||
expect(f3Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f1', 'g1', 'h1']);
|
||||
expect(f4Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e1', 'f1', 'g1', 'h1']);
|
||||
expect(f5Comp !.names).toEqual(['a', 'b', 'c', 'd1', 'e1', 'f1', 'g1', 'h1']);
|
||||
|
@ -255,7 +259,7 @@ describe('array literals', () => {
|
|||
expect(f7Comp !.names).toEqual(['a', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1']);
|
||||
expect(f8Comp !.names).toEqual(['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1']);
|
||||
|
||||
renderToHtml(Template, ['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h2', 'i1']);
|
||||
renderToHtml(Template, ['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h2', 'i1'], defs);
|
||||
expect(f3Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f1', 'g1', 'h2']);
|
||||
expect(f4Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e1', 'f1', 'g1', 'h2']);
|
||||
expect(f5Comp !.names).toEqual(['a', 'b', 'c', 'd1', 'e1', 'f1', 'g1', 'h2']);
|
||||
|
@ -270,14 +274,14 @@ describe('array literals', () => {
|
|||
v8: any) => ['start', v0, v1, v2, v3, v4, v5, v6, v7, v8, 'end'];
|
||||
const e0_ff_1 = (v: any) => { return {name: v}; };
|
||||
|
||||
renderToHtml(Template, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']);
|
||||
renderToHtml(Template, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], defs);
|
||||
/**
|
||||
* <my-comp [names]="['start', v0, v1, v2, v3, {name: v4}, v5, v6, v7, v8, 'end']">
|
||||
* </my-comp>
|
||||
*/
|
||||
function Template(c: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, MyComp);
|
||||
elementStart(0, 'my-comp');
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'names', bind(pureFunctionV(e0_ff, [
|
||||
|
@ -289,12 +293,12 @@ describe('array literals', () => {
|
|||
'start', 'a', 'b', 'c', 'd', {name: 'e'}, 'f', 'g', 'h', 'i', 'end'
|
||||
]);
|
||||
|
||||
renderToHtml(Template, ['a1', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']);
|
||||
renderToHtml(Template, ['a1', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], defs);
|
||||
expect(myComp !.names).toEqual([
|
||||
'start', 'a1', 'b', 'c', 'd', {name: 'e'}, 'f', 'g', 'h', 'i', 'end'
|
||||
]);
|
||||
|
||||
renderToHtml(Template, ['a1', 'b', 'c', 'd', 'e5', 'f', 'g', 'h', 'i']);
|
||||
renderToHtml(Template, ['a1', 'b', 'c', 'd', 'e5', 'f', 'g', 'h', 'i'], defs);
|
||||
expect(myComp !.names).toEqual([
|
||||
'start', 'a1', 'b', 'c', 'd', {name: 'e5'}, 'f', 'g', 'h', 'i', 'end'
|
||||
]);
|
||||
|
@ -309,34 +313,36 @@ describe('object literals', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: ObjectComp,
|
||||
tag: 'object-comp',
|
||||
selector: [[['object-comp'], null]],
|
||||
factory: function ObjectComp_Factory() { return objectComp = new ObjectComp(); },
|
||||
template: function ObjectComp_Template(ctx: ObjectComp, cm: boolean) {},
|
||||
inputs: {config: 'config'}
|
||||
});
|
||||
}
|
||||
|
||||
const defs = [ObjectComp.ngComponentDef];
|
||||
|
||||
it('should support an object literal', () => {
|
||||
const e0_ff = (v: any) => { return {duration: 500, animation: v}; };
|
||||
|
||||
/** <object-comp [config]="{duration: 500, animation: name}"></object-comp> */
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, ObjectComp);
|
||||
elementStart(0, 'object-comp');
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(0, 'config', bind(pureFunction1(e0_ff, ctx.name)));
|
||||
}
|
||||
|
||||
renderToHtml(Template, {name: 'slide'});
|
||||
renderToHtml(Template, {name: 'slide'}, defs);
|
||||
const firstObj = objectComp !.config;
|
||||
expect(objectComp !.config).toEqual({duration: 500, animation: 'slide'});
|
||||
|
||||
renderToHtml(Template, {name: 'slide'});
|
||||
renderToHtml(Template, {name: 'slide'}, defs);
|
||||
expect(objectComp !.config).toEqual({duration: 500, animation: 'slide'});
|
||||
expect(firstObj).toBe(objectComp !.config);
|
||||
|
||||
renderToHtml(Template, {name: 'tap'});
|
||||
renderToHtml(Template, {name: 'tap'}, defs);
|
||||
expect(objectComp !.config).toEqual({duration: 500, animation: 'tap'});
|
||||
|
||||
// Identity must change if binding changes
|
||||
|
@ -355,7 +361,7 @@ describe('object literals', () => {
|
|||
*/
|
||||
function Template(ctx: any, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, ObjectComp);
|
||||
elementStart(0, 'object-comp');
|
||||
elementEnd();
|
||||
}
|
||||
elementProperty(
|
||||
|
@ -364,34 +370,34 @@ describe('object literals', () => {
|
|||
e0_ff, ctx.name, pureFunction1(e0_ff_1, pureFunction1(e0_ff_2, ctx.duration)))));
|
||||
}
|
||||
|
||||
renderToHtml(Template, {name: 'slide', duration: 100});
|
||||
renderToHtml(Template, {name: 'slide', duration: 100}, defs);
|
||||
expect(objectComp !.config).toEqual({
|
||||
animation: 'slide',
|
||||
actions: [{opacity: 0, duration: 0}, {opacity: 1, duration: 100}]
|
||||
});
|
||||
const firstConfig = objectComp !.config;
|
||||
|
||||
renderToHtml(Template, {name: 'slide', duration: 100});
|
||||
renderToHtml(Template, {name: 'slide', duration: 100}, defs);
|
||||
expect(objectComp !.config).toEqual({
|
||||
animation: 'slide',
|
||||
actions: [{opacity: 0, duration: 0}, {opacity: 1, duration: 100}]
|
||||
});
|
||||
expect(objectComp !.config).toBe(firstConfig);
|
||||
|
||||
renderToHtml(Template, {name: 'slide', duration: 50});
|
||||
renderToHtml(Template, {name: 'slide', duration: 50}, defs);
|
||||
expect(objectComp !.config).toEqual({
|
||||
animation: 'slide',
|
||||
actions: [{opacity: 0, duration: 0}, {opacity: 1, duration: 50}]
|
||||
});
|
||||
expect(objectComp !.config).not.toBe(firstConfig);
|
||||
|
||||
renderToHtml(Template, {name: 'tap', duration: 50});
|
||||
renderToHtml(Template, {name: 'tap', duration: 50}, defs);
|
||||
expect(objectComp !.config).toEqual({
|
||||
animation: 'tap',
|
||||
actions: [{opacity: 0, duration: 0}, {opacity: 1, duration: 50}]
|
||||
});
|
||||
|
||||
renderToHtml(Template, {name: 'drag', duration: 500});
|
||||
renderToHtml(Template, {name: 'drag', duration: 500}, defs);
|
||||
expect(objectComp !.config).toEqual({
|
||||
animation: 'drag',
|
||||
actions: [{opacity: 0, duration: 0}, {opacity: 1, duration: 500}]
|
||||
|
@ -400,7 +406,7 @@ describe('object literals', () => {
|
|||
// The property should not be set if the exp value is the same, so artificially
|
||||
// setting the property to ensure it's not overwritten.
|
||||
objectComp !.config = ['should not be overwritten'];
|
||||
renderToHtml(Template, {name: 'drag', duration: 500});
|
||||
renderToHtml(Template, {name: 'drag', duration: 500}, defs);
|
||||
expect(objectComp !.config).toEqual(['should not be overwritten']);
|
||||
});
|
||||
|
||||
|
@ -421,7 +427,7 @@ describe('object literals', () => {
|
|||
{
|
||||
for (let i = 0; i < 2; i++) {
|
||||
if (embeddedViewStart(0)) {
|
||||
elementStart(0, ObjectComp);
|
||||
elementStart(0, 'object-comp');
|
||||
objectComps.push(loadDirective(0));
|
||||
elementEnd();
|
||||
}
|
||||
|
@ -437,12 +443,12 @@ describe('object literals', () => {
|
|||
const e0_ff = (v1: any, v2: any) => { return {opacity: v1, duration: v2}; };
|
||||
|
||||
const configs = [{opacity: 0, duration: 500}, {opacity: 1, duration: 600}];
|
||||
renderToHtml(Template, {configs});
|
||||
renderToHtml(Template, {configs}, defs);
|
||||
expect(objectComps[0].config).toEqual({opacity: 0, duration: 500});
|
||||
expect(objectComps[1].config).toEqual({opacity: 1, duration: 600});
|
||||
|
||||
configs[0].duration = 1000;
|
||||
renderToHtml(Template, {configs});
|
||||
renderToHtml(Template, {configs}, defs);
|
||||
expect(objectComps[0].config).toEqual({opacity: 0, duration: 1000});
|
||||
expect(objectComps[1].config).toEqual({opacity: 1, duration: 600});
|
||||
});
|
||||
|
|
|
@ -62,10 +62,10 @@ describe('query', () => {
|
|||
if (cm) {
|
||||
query(0, Child, false);
|
||||
query(1, Child, true);
|
||||
elementStart(2, Child);
|
||||
elementStart(2, 'child');
|
||||
{
|
||||
child1 = loadDirective(0);
|
||||
elementStart(3, Child);
|
||||
elementStart(3, 'child');
|
||||
{ child2 = loadDirective(1); }
|
||||
elementEnd();
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ describe('query', () => {
|
|||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query0 = tmp as QueryList<any>);
|
||||
queryRefresh(tmp = load<QueryList<any>>(1)) && (ctx.query1 = tmp as QueryList<any>);
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const parent = renderComponent(Cmp);
|
||||
expect((parent.query0 as QueryList<any>).toArray()).toEqual([child1]);
|
||||
|
@ -83,7 +83,7 @@ describe('query', () => {
|
|||
describe('types predicate', () => {
|
||||
|
||||
it('should query using type predicate and read a specified token', () => {
|
||||
const Child = createDirective();
|
||||
const Child = createDirective('child');
|
||||
let elToQuery;
|
||||
/**
|
||||
* <div child></div>
|
||||
|
@ -95,11 +95,11 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, Child, false, QUERY_READ_ELEMENT_REF);
|
||||
elToQuery = elementStart(1, 'div', null, [Child]);
|
||||
elToQuery = elementStart(1, 'div', ['child', '']);
|
||||
elementEnd();
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
});
|
||||
}, [Child.ngDirectiveDef]);
|
||||
|
||||
const cmptInstance = renderComponent(Cmpt);
|
||||
const qList = (cmptInstance.query as QueryList<any>);
|
||||
|
@ -110,8 +110,8 @@ describe('query', () => {
|
|||
|
||||
|
||||
it('should query using type predicate and read another directive type', () => {
|
||||
const Child = createDirective();
|
||||
const OtherChild = createDirective();
|
||||
const Child = createDirective('child');
|
||||
const OtherChild = createDirective('otherChild');
|
||||
let otherChildInstance;
|
||||
/**
|
||||
* <div child otherChild></div>
|
||||
|
@ -123,12 +123,12 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, Child, false, OtherChild);
|
||||
elementStart(1, 'div', null, [Child, OtherChild]);
|
||||
elementStart(1, 'div', ['child', '', 'otherChild', '']);
|
||||
{ otherChildInstance = loadDirective(1); }
|
||||
elementEnd();
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
});
|
||||
}, [Child.ngDirectiveDef, OtherChild.ngDirectiveDef]);
|
||||
|
||||
const cmptInstance = renderComponent(Cmpt);
|
||||
const qList = (cmptInstance.query as QueryList<any>);
|
||||
|
@ -137,8 +137,8 @@ describe('query', () => {
|
|||
});
|
||||
|
||||
it('should not add results to query if a requested token cant be read', () => {
|
||||
const Child = createDirective();
|
||||
const OtherChild = createDirective();
|
||||
const Child = createDirective('child');
|
||||
const OtherChild = createDirective('otherChild');
|
||||
/**
|
||||
* <div child></div>
|
||||
* class Cmpt {
|
||||
|
@ -149,11 +149,11 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, Child, false, OtherChild);
|
||||
elementStart(1, 'div', null, [Child]);
|
||||
elementStart(1, 'div', ['child', '']);
|
||||
elementEnd();
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
});
|
||||
}, [Child.ngDirectiveDef, OtherChild.ngDirectiveDef]);
|
||||
|
||||
const cmptInstance = renderComponent(Cmpt);
|
||||
const qList = (cmptInstance.query as QueryList<any>);
|
||||
|
@ -177,7 +177,7 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo'], false, QUERY_READ_FROM_NODE);
|
||||
elToQuery = elementStart(1, 'div', null, null, ['foo', '']);
|
||||
elToQuery = elementStart(1, 'div', null, ['foo', '']);
|
||||
elementEnd();
|
||||
elementStart(2, 'div');
|
||||
elementEnd();
|
||||
|
@ -207,7 +207,7 @@ describe('query', () => {
|
|||
if (cm) {
|
||||
query(0, ['foo'], false, QUERY_READ_FROM_NODE);
|
||||
query(1, ['bar'], false, QUERY_READ_FROM_NODE);
|
||||
elToQuery = elementStart(2, 'div', null, null, ['foo', '', 'bar', '']);
|
||||
elToQuery = elementStart(2, 'div', null, ['foo', '', 'bar', '']);
|
||||
elementEnd();
|
||||
elementStart(3, 'div');
|
||||
elementEnd();
|
||||
|
@ -243,11 +243,11 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE);
|
||||
el1ToQuery = elementStart(1, 'div', null, null, ['foo', '']);
|
||||
el1ToQuery = elementStart(1, 'div', null, ['foo', '']);
|
||||
elementEnd();
|
||||
elementStart(2, 'div');
|
||||
elementEnd();
|
||||
el2ToQuery = elementStart(3, 'div', null, null, ['bar', '']);
|
||||
el2ToQuery = elementStart(3, 'div', null, ['bar', '']);
|
||||
elementEnd();
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
|
@ -274,7 +274,7 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo'], false, QUERY_READ_ELEMENT_REF);
|
||||
elToQuery = elementStart(1, 'div', null, null, ['foo', '']);
|
||||
elToQuery = elementStart(1, 'div', null, ['foo', '']);
|
||||
elementEnd();
|
||||
elementStart(2, 'div');
|
||||
elementEnd();
|
||||
|
@ -300,7 +300,7 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo'], false, QUERY_READ_CONTAINER_REF);
|
||||
elementStart(1, 'div', null, null, ['foo', '']);
|
||||
elementStart(1, 'div', null, ['foo', '']);
|
||||
elementEnd();
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
|
@ -323,7 +323,7 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo'], false, QUERY_READ_CONTAINER_REF);
|
||||
container(1, undefined, undefined, undefined, undefined, ['foo', '']);
|
||||
container(1, undefined, undefined, undefined, ['foo', '']);
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
});
|
||||
|
@ -346,7 +346,7 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo'], false, QUERY_READ_ELEMENT_REF);
|
||||
container(1, undefined, undefined, undefined, undefined, ['foo', '']);
|
||||
container(1, undefined, undefined, undefined, ['foo', '']);
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
});
|
||||
|
@ -369,7 +369,7 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo'], undefined, QUERY_READ_FROM_NODE);
|
||||
container(1, undefined, undefined, undefined, undefined, ['foo', '']);
|
||||
container(1, undefined, undefined, undefined, ['foo', '']);
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
});
|
||||
|
@ -392,7 +392,7 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo'], false, QUERY_READ_TEMPLATE_REF);
|
||||
container(1, undefined, undefined, undefined, undefined, ['foo', '']);
|
||||
container(1, undefined, undefined, undefined, ['foo', '']);
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
});
|
||||
|
@ -417,12 +417,12 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
|
||||
elementStart(1, Child, null, null, ['foo', '']);
|
||||
elementStart(1, 'child', null, ['foo', '']);
|
||||
{ childInstance = loadDirective(0); }
|
||||
elementEnd();
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const cmptInstance = renderComponent(Cmpt);
|
||||
const qList = (cmptInstance.query as QueryList<any>);
|
||||
|
@ -436,7 +436,7 @@ describe('query', () => {
|
|||
class Child {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: Child,
|
||||
tag: 'child',
|
||||
selector: [[['child'], null]],
|
||||
factory: () => childInstance = new Child(),
|
||||
template: (ctx: Child, cm: boolean) => {},
|
||||
exportAs: 'child'
|
||||
|
@ -453,11 +453,11 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
|
||||
elementStart(1, Child, null, null, ['foo', 'child']);
|
||||
elementStart(1, 'child', null, ['foo', 'child']);
|
||||
elementEnd();
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
});
|
||||
}, [Child.ngComponentDef]);
|
||||
|
||||
const cmptInstance = renderComponent(Cmpt);
|
||||
const qList = (cmptInstance.query as QueryList<any>);
|
||||
|
@ -467,7 +467,7 @@ describe('query', () => {
|
|||
|
||||
it('should read directive instance if element queried for has an exported directive with a matching name',
|
||||
() => {
|
||||
const Child = createDirective({exportAs: 'child'});
|
||||
const Child = createDirective('child', {exportAs: 'child'});
|
||||
|
||||
let childInstance;
|
||||
/**
|
||||
|
@ -480,12 +480,12 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
|
||||
elementStart(1, 'div', null, [Child], ['foo', 'child']);
|
||||
elementStart(1, 'div', ['child', ''], ['foo', 'child']);
|
||||
childInstance = loadDirective(0);
|
||||
elementEnd();
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
});
|
||||
}, [Child.ngDirectiveDef]);
|
||||
|
||||
const cmptInstance = renderComponent(Cmpt);
|
||||
const qList = (cmptInstance.query as QueryList<any>);
|
||||
|
@ -494,8 +494,8 @@ describe('query', () => {
|
|||
});
|
||||
|
||||
it('should read all matching directive instances from a given element', () => {
|
||||
const Child1 = createDirective({exportAs: 'child1'});
|
||||
const Child2 = createDirective({exportAs: 'child2'});
|
||||
const Child1 = createDirective('child1', {exportAs: 'child1'});
|
||||
const Child2 = createDirective('child2', {exportAs: 'child2'});
|
||||
|
||||
let child1Instance, child2Instance;
|
||||
/**
|
||||
|
@ -508,7 +508,7 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo', 'bar'], true, QUERY_READ_FROM_NODE);
|
||||
elementStart(1, 'div', null, [Child1, Child2], ['foo', 'child1', 'bar', 'child2']);
|
||||
elementStart(1, 'div', ['child1', '', 'child2', ''], ['foo', 'child1', 'bar', 'child2']);
|
||||
{
|
||||
child1Instance = loadDirective(0);
|
||||
child2Instance = loadDirective(1);
|
||||
|
@ -516,7 +516,7 @@ describe('query', () => {
|
|||
elementEnd();
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
});
|
||||
}, [Child1.ngDirectiveDef, Child2.ngDirectiveDef]);
|
||||
|
||||
const cmptInstance = renderComponent(Cmpt);
|
||||
const qList = (cmptInstance.query as QueryList<any>);
|
||||
|
@ -526,7 +526,7 @@ describe('query', () => {
|
|||
});
|
||||
|
||||
it('should read multiple locals exporting the same directive from a given element', () => {
|
||||
const Child = createDirective({exportAs: 'child'});
|
||||
const Child = createDirective('child', {exportAs: 'child'});
|
||||
let childInstance;
|
||||
|
||||
/**
|
||||
|
@ -541,13 +541,13 @@ describe('query', () => {
|
|||
if (cm) {
|
||||
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
|
||||
query(1, ['bar'], true, QUERY_READ_FROM_NODE);
|
||||
elementStart(2, 'div', null, [Child], ['foo', 'child', 'bar', 'child']);
|
||||
elementStart(2, 'div', ['child', ''], ['foo', 'child', 'bar', 'child']);
|
||||
{ childInstance = loadDirective(0); }
|
||||
elementEnd();
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.fooQuery = tmp as QueryList<any>);
|
||||
queryRefresh(tmp = load<QueryList<any>>(1)) && (ctx.barQuery = tmp as QueryList<any>);
|
||||
});
|
||||
}, [Child.ngDirectiveDef]);
|
||||
|
||||
const cmptInstance = renderComponent(Cmpt);
|
||||
|
||||
|
@ -561,7 +561,7 @@ describe('query', () => {
|
|||
});
|
||||
|
||||
it('should match on exported directive name and read a requested token', () => {
|
||||
const Child = createDirective({exportAs: 'child'});
|
||||
const Child = createDirective('child', {exportAs: 'child'});
|
||||
|
||||
let div;
|
||||
/**
|
||||
|
@ -574,11 +574,11 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo'], undefined, QUERY_READ_ELEMENT_REF);
|
||||
div = elementStart(1, 'div', null, [Child], ['foo', 'child']);
|
||||
div = elementStart(1, 'div', ['child', ''], ['foo', 'child']);
|
||||
elementEnd();
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
});
|
||||
}, [Child.ngDirectiveDef]);
|
||||
|
||||
const cmptInstance = renderComponent(Cmpt);
|
||||
const qList = (cmptInstance.query as QueryList<any>);
|
||||
|
@ -587,7 +587,7 @@ describe('query', () => {
|
|||
});
|
||||
|
||||
it('should support reading a mix of ElementRef and directive instances', () => {
|
||||
const Child = createDirective({exportAs: 'child'});
|
||||
const Child = createDirective('child', {exportAs: 'child'});
|
||||
|
||||
let childInstance, div;
|
||||
/**
|
||||
|
@ -600,12 +600,12 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo', 'bar'], undefined, QUERY_READ_FROM_NODE);
|
||||
div = elementStart(1, 'div', null, [Child], ['foo', '', 'bar', 'child']);
|
||||
div = elementStart(1, 'div', ['child', ''], ['foo', '', 'bar', 'child']);
|
||||
{ childInstance = loadDirective(0); }
|
||||
elementEnd();
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
});
|
||||
}, [Child.ngDirectiveDef]);
|
||||
|
||||
const cmptInstance = renderComponent(Cmpt);
|
||||
const qList = (cmptInstance.query as QueryList<any>);
|
||||
|
@ -615,7 +615,7 @@ describe('query', () => {
|
|||
});
|
||||
|
||||
it('should not add results to query if a requested token cant be read', () => {
|
||||
const Child = createDirective();
|
||||
const Child = createDirective('child');
|
||||
|
||||
/**
|
||||
* <div #foo></div>
|
||||
|
@ -627,11 +627,11 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo'], false, Child);
|
||||
elementStart(1, 'div', null, null, ['foo', '']);
|
||||
elementStart(1, 'div', ['foo', '']);
|
||||
elementEnd();
|
||||
}
|
||||
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
|
||||
});
|
||||
}, [Child.ngDirectiveDef]);
|
||||
|
||||
const cmptInstance = renderComponent(Cmpt);
|
||||
const qList = (cmptInstance.query as QueryList<any>);
|
||||
|
@ -664,7 +664,7 @@ describe('query', () => {
|
|||
let cm1 = embeddedViewStart(1);
|
||||
{
|
||||
if (cm1) {
|
||||
firstEl = elementStart(0, 'div', null, null, ['foo', '']);
|
||||
firstEl = elementStart(0, 'div', null, ['foo', '']);
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
@ -706,10 +706,10 @@ describe('query', () => {
|
|||
let tmp: any;
|
||||
if (cm) {
|
||||
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
|
||||
firstEl = elementStart(1, 'b', null, null, ['foo', '']);
|
||||
firstEl = elementStart(1, 'span', null, ['foo', '']);
|
||||
elementEnd();
|
||||
container(2);
|
||||
lastEl = elementStart(3, 'i', null, null, ['foo', '']);
|
||||
lastEl = elementStart(3, 'span', null, ['foo', '']);
|
||||
elementEnd();
|
||||
}
|
||||
containerRefreshStart(2);
|
||||
|
@ -718,7 +718,7 @@ describe('query', () => {
|
|||
let cm1 = embeddedViewStart(1);
|
||||
{
|
||||
if (cm1) {
|
||||
viewEl = elementStart(0, 'div', null, null, ['foo', '']);
|
||||
viewEl = elementStart(0, 'div', null, ['foo', '']);
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
@ -774,7 +774,7 @@ describe('query', () => {
|
|||
let cm1 = embeddedViewStart(0);
|
||||
{
|
||||
if (cm1) {
|
||||
firstEl = elementStart(0, 'div', null, null, ['foo', '']);
|
||||
firstEl = elementStart(0, 'div', null, ['foo', '']);
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
@ -784,7 +784,7 @@ describe('query', () => {
|
|||
let cm1 = embeddedViewStart(1);
|
||||
{
|
||||
if (cm1) {
|
||||
lastEl = elementStart(0, 'span', null, null, ['foo', '']);
|
||||
lastEl = elementStart(0, 'span', null, ['foo', '']);
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
@ -836,7 +836,7 @@ describe('query', () => {
|
|||
let cm1 = embeddedViewStart(0);
|
||||
{
|
||||
if (cm1) {
|
||||
firstEl = elementStart(0, 'div', null, null, ['foo', '']);
|
||||
firstEl = elementStart(0, 'div', null, ['foo', '']);
|
||||
elementEnd();
|
||||
container(1);
|
||||
}
|
||||
|
@ -846,7 +846,7 @@ describe('query', () => {
|
|||
let cm2 = embeddedViewStart(0);
|
||||
{
|
||||
if (cm2) {
|
||||
lastEl = elementStart(0, 'span', null, null, ['foo', '']);
|
||||
lastEl = elementStart(0, 'span', null, ['foo', '']);
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
@ -894,7 +894,7 @@ describe('query', () => {
|
|||
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
|
||||
query(1, ['foo'], false, QUERY_READ_FROM_NODE);
|
||||
container(2);
|
||||
elementStart(3, 'span', null, null, ['foo', '']);
|
||||
elementStart(3, 'span', null, ['foo', '']);
|
||||
elementEnd();
|
||||
}
|
||||
containerRefreshStart(2);
|
||||
|
@ -903,7 +903,7 @@ describe('query', () => {
|
|||
let cm1 = embeddedViewStart(0);
|
||||
{
|
||||
if (cm1) {
|
||||
elementStart(0, 'div', null, null, ['foo', '']);
|
||||
elementStart(0, 'div', null, ['foo', '']);
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import {stringifyElement} from '@angular/platform-browser/testing/src/browser_util';
|
||||
|
||||
import {CreateComponentOptions} from '../../src/render3/component';
|
||||
import {ComponentTemplate, ComponentType, DirectiveType, PublicFeature, defineComponent, defineDirective, renderComponent as _renderComponent, tick} from '../../src/render3/index';
|
||||
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveType, PublicFeature, defineComponent, defineDirective, renderComponent as _renderComponent, tick} from '../../src/render3/index';
|
||||
import {NG_HOST_SYMBOL, renderTemplate} from '../../src/render3/instructions';
|
||||
import {LElementNode} from '../../src/render3/interfaces/node';
|
||||
import {RElement, RText, Renderer3, RendererFactory3, domRendererFactory3} from '../../src/render3/interfaces/renderer';
|
||||
|
@ -151,9 +151,10 @@ export function resetDOM() {
|
|||
* @deprecated use `TemplateFixture` or `ComponentFixture`
|
||||
*/
|
||||
export function renderToHtml(
|
||||
template: ComponentTemplate<any>, ctx: any, providedRendererFactory?: RendererFactory3) {
|
||||
template: ComponentTemplate<any>, ctx: any, defs?: any[],
|
||||
providedRendererFactory?: RendererFactory3 | null) {
|
||||
host = renderTemplate(
|
||||
containerEl, template, ctx, providedRendererFactory || testRendererFactory, host);
|
||||
containerEl, template, ctx, providedRendererFactory || testRendererFactory, host, defs);
|
||||
return toHtml(containerEl);
|
||||
}
|
||||
|
||||
|
@ -188,23 +189,27 @@ export function toHtml<T>(componentOrElement: T | RElement): string {
|
|||
}
|
||||
|
||||
export function createComponent(
|
||||
name: string, template: ComponentTemplate<any>): ComponentType<any> {
|
||||
name: string, template: ComponentTemplate<any>,
|
||||
defs: (ComponentDef<any>| DirectiveDef<any>)[] = []): ComponentType<any> {
|
||||
return class Component {
|
||||
value: any;
|
||||
static ngComponentDef = defineComponent({
|
||||
type: Component,
|
||||
tag: name,
|
||||
selector: [[[name], null]],
|
||||
factory: () => new Component,
|
||||
template: template,
|
||||
features: [PublicFeature]
|
||||
features: [PublicFeature],
|
||||
directiveDefs: () => defs
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function createDirective({exportAs}: {exportAs?: string} = {}): DirectiveType<any> {
|
||||
export function createDirective(
|
||||
name: string, {exportAs}: {exportAs?: string} = {}): DirectiveType<any> {
|
||||
return class Directive {
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: Directive,
|
||||
selector: [[['', name, ''], null]],
|
||||
factory: () => new Directive(),
|
||||
features: [PublicFeature],
|
||||
exportAs: exportAs,
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('renderer factory lifecycle', () => {
|
|||
class SomeComponent {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: SomeComponent,
|
||||
tag: 'some-component',
|
||||
selector: [[['some-component'], null]],
|
||||
template: function(ctx: SomeComponent, cm: boolean) {
|
||||
logs.push('component');
|
||||
if (cm) {
|
||||
|
@ -45,7 +45,7 @@ describe('renderer factory lifecycle', () => {
|
|||
class SomeComponentWhichThrows {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: SomeComponentWhichThrows,
|
||||
tag: 'some-component-with-Error',
|
||||
selector: [[['some-component-with-Error'], null]],
|
||||
template: function(ctx: SomeComponentWhichThrows, cm: boolean) {
|
||||
throw(new Error('SomeComponentWhichThrows threw'));
|
||||
},
|
||||
|
@ -60,11 +60,13 @@ describe('renderer factory lifecycle', () => {
|
|||
}
|
||||
}
|
||||
|
||||
const defs = [SomeComponent.ngComponentDef, SomeComponentWhichThrows.ngComponentDef];
|
||||
|
||||
function TemplateWithComponent(ctx: any, cm: boolean) {
|
||||
logs.push('function_with_component');
|
||||
if (cm) {
|
||||
text(0, 'bar');
|
||||
elementStart(1, SomeComponent);
|
||||
elementStart(1, 'some-component');
|
||||
elementEnd();
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +88,7 @@ describe('renderer factory lifecycle', () => {
|
|||
});
|
||||
|
||||
it('should work with a template', () => {
|
||||
renderToHtml(Template, {}, rendererFactory);
|
||||
renderToHtml(Template, {}, [], rendererFactory);
|
||||
expect(logs).toEqual(['create', 'begin', 'function', 'end']);
|
||||
|
||||
logs = [];
|
||||
|
@ -95,12 +97,12 @@ describe('renderer factory lifecycle', () => {
|
|||
});
|
||||
|
||||
it('should work with a template which contains a component', () => {
|
||||
renderToHtml(TemplateWithComponent, {}, rendererFactory);
|
||||
renderToHtml(TemplateWithComponent, {}, defs, rendererFactory);
|
||||
expect(logs).toEqual(
|
||||
['create', 'begin', 'function_with_component', 'create', 'component', 'end']);
|
||||
|
||||
logs = [];
|
||||
renderToHtml(TemplateWithComponent, {});
|
||||
renderToHtml(TemplateWithComponent, {}, defs);
|
||||
expect(logs).toEqual(['begin', 'function_with_component', 'component', 'end']);
|
||||
});
|
||||
|
||||
|
@ -122,7 +124,7 @@ describe('animation renderer factory', () => {
|
|||
class SomeComponent {
|
||||
static ngComponentDef = defineComponent({
|
||||
type: SomeComponent,
|
||||
tag: 'some-component',
|
||||
selector: [[['some-component'], null]],
|
||||
template: function(ctx: SomeComponent, cm: boolean) {
|
||||
if (cm) {
|
||||
text(0, 'foo');
|
||||
|
@ -139,7 +141,7 @@ describe('animation renderer factory', () => {
|
|||
}
|
||||
static ngComponentDef = defineComponent({
|
||||
type: SomeComponentWithAnimation,
|
||||
tag: 'some-component',
|
||||
selector: [[['some-component'], null]],
|
||||
template: function(ctx: SomeComponentWithAnimation, cm: boolean) {
|
||||
if (cm) {
|
||||
elementStart(0, 'div');
|
||||
|
|
|
@ -18,6 +18,7 @@ describe('ViewContainerRef', () => {
|
|||
|
||||
static ngDirectiveDef = defineDirective({
|
||||
type: TestDirective,
|
||||
selector: [[['', 'testDir', ''], null]],
|
||||
factory: () => new TestDirective(injectViewContainerRef(), injectTemplateRef(), ),
|
||||
});
|
||||
}
|
||||
|
@ -27,7 +28,7 @@ describe('ViewContainerRef', () => {
|
|||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: TestComponent,
|
||||
tag: 'test-cmp',
|
||||
selector: [[['test-cmp'], null]],
|
||||
factory: () => new TestComponent(),
|
||||
template: (cmp: TestComponent, cm: boolean) => {
|
||||
if (cm) {
|
||||
|
@ -37,12 +38,13 @@ describe('ViewContainerRef', () => {
|
|||
}
|
||||
textBinding(0, bind(ctx.$implicit));
|
||||
};
|
||||
container(0, [TestDirective], subTemplate);
|
||||
container(0, subTemplate, undefined, ['testDir', '']);
|
||||
}
|
||||
containerRefreshStart(0);
|
||||
cmp.testDir = loadDirective<TestDirective>(0);
|
||||
containerRefreshEnd();
|
||||
},
|
||||
directiveDefs: [TestDirective.ngDirectiveDef]
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue