From 49082d7ab2d602ff72fb03db2259d4f68bf2578b Mon Sep 17 00:00:00 2001 From: Kara Erickson Date: Fri, 16 Feb 2018 12:09:47 -0800 Subject: [PATCH] feat(ivy): support host attributes (#22213) PR Close #22213 --- packages/core/src/render3/definition.ts | 3 +- packages/core/src/render3/instructions.ts | 6 +++ .../core/src/render3/interfaces/definition.ts | 9 ++++ .../compiler_canonical_spec.ts | 43 +++++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/packages/core/src/render3/definition.ts b/packages/core/src/render3/definition.ts index da7f24d4b8..cfd5c97e99 100644 --- a/packages/core/src/render3/definition.ts +++ b/packages/core/src/render3/definition.ts @@ -42,6 +42,7 @@ export function defineComponent(componentDefinition: ComponentDefArgs): Co tag: (componentDefinition as ComponentDefArgs).tag || null !, template: (componentDefinition as ComponentDefArgs).template || null !, h: componentDefinition.hostBindings || noop, + attributes: componentDefinition.attributes || null, inputs: invertObject(componentDefinition.inputs), outputs: invertObject(componentDefinition.outputs), methods: invertObject(componentDefinition.methods), @@ -177,4 +178,4 @@ export function definePipe( {type, factory, pure}: {type: Type, factory: () => PipeTransform, pure?: boolean}): PipeDef { throw new Error('TODO: implement!'); -} \ No newline at end of file +} diff --git a/packages/core/src/render3/instructions.ts b/packages/core/src/render3/instructions.ts index 819d200f2b..d22ec58195 100644 --- a/packages/core/src/render3/instructions.ts +++ b/packages/core/src/render3/instructions.ts @@ -910,6 +910,12 @@ export function directiveCreate( diPublic(directiveDef !); } + if (directiveDef !.attributes != null && + (previousOrParentNode.flags & LNodeFlags.TYPE_MASK) == LNodeFlags.Element) { + setUpAttributes( + (previousOrParentNode as LElementNode).native, directiveDef !.attributes as string[]); + } + const tNode: TNode|null = previousOrParentNode.tNode !; if (tNode && tNode.attrs) { setInputsFromAttrs(instance, directiveDef !.inputs, tNode); diff --git a/packages/core/src/render3/interfaces/definition.ts b/packages/core/src/render3/interfaces/definition.ts index ed95c7a986..6689add43c 100644 --- a/packages/core/src/render3/interfaces/definition.ts +++ b/packages/core/src/render3/interfaces/definition.ts @@ -79,6 +79,14 @@ export interface DirectiveDef { */ h(directiveIndex: number, elementIndex: number): void; + /** + * Static attributes to set on host element. + * + * Even indices: attribute name + * Odd indices: attribute value + */ + attributes: string[]|null; + /* The following are lifecycle hooks for this component */ onInit: (() => void)|null; doCheck: (() => void)|null; @@ -140,6 +148,7 @@ export interface PipeDef { export interface DirectiveDefArgs { type: Type; factory: () => T | [T]; + attributes?: string[]; inputs?: {[P in keyof T]?: string}; outputs?: {[P in keyof T]?: string}; methods?: {[P in keyof T]?: string}; diff --git a/packages/core/test/render3/compiler_canonical/compiler_canonical_spec.ts b/packages/core/test/render3/compiler_canonical/compiler_canonical_spec.ts index accd1e85f9..04cb0ab172 100644 --- a/packages/core/test/render3/compiler_canonical/compiler_canonical_spec.ts +++ b/packages/core/test/render3/compiler_canonical/compiler_canonical_spec.ts @@ -225,6 +225,49 @@ describe('compiler specification', () => { expect(renderComp(MyApp)).toEqual(``); }); + + it('should support setting of host attributes', () => { + type $MyApp$ = MyApp; + + @Directive({selector: '[hostAttributeDir]', host: {'role': 'listbox'}}) + class HostAttributeDir { + // NORMATIVE + static ngDirectiveDef = $r3$.ɵdefineDirective({ + type: HostAttributeDir, + factory: function HostAttributeDir_Factory() { return new HostAttributeDir(); }, + attributes: ['role', 'listbox'] + }); + // /NORMATIVE + } + + const $e0_attrs$ = ['hostAttributeDir', '']; + const $e0_dirs$ = [HostAttributeDir]; + + @Component({ + selector: 'my-app', + template: ` +
+ ` + }) + class MyApp { + static ngComponentDef = $r3$.ɵdefineComponent({ + type: MyApp, + tag: 'my-app', + 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(); + } + HostAttributeDir.ngDirectiveDef.h(1, 0); + $r3$.ɵr(1, 0); + } + }); + } + + expect(renderComp(MyApp)).toEqual(`
`); + }); + it('should support bindings of host attributes', () => { type $MyApp$ = MyApp;