feat(ivy): support host attributes (#22213)

PR Close #22213
This commit is contained in:
Kara Erickson 2018-02-16 12:09:47 -08:00 committed by Victor Berchet
parent 6b627f67db
commit 49082d7ab2
4 changed files with 60 additions and 1 deletions

View File

@ -42,6 +42,7 @@ export function defineComponent<T>(componentDefinition: ComponentDefArgs<T>): Co
tag: (componentDefinition as ComponentDefArgs<T>).tag || null !,
template: (componentDefinition as ComponentDefArgs<T>).template || null !,
h: componentDefinition.hostBindings || noop,
attributes: componentDefinition.attributes || null,
inputs: invertObject(componentDefinition.inputs),
outputs: invertObject(componentDefinition.outputs),
methods: invertObject(componentDefinition.methods),

View File

@ -910,6 +910,12 @@ export function directiveCreate<T>(
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<T>(instance, directiveDef !.inputs, tNode);

View File

@ -79,6 +79,14 @@ export interface DirectiveDef<T> {
*/
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<T> {
export interface DirectiveDefArgs<T> {
type: Type<T>;
factory: () => T | [T];
attributes?: string[];
inputs?: {[P in keyof T]?: string};
outputs?: {[P in keyof T]?: string};
methods?: {[P in keyof T]?: string};

View File

@ -225,6 +225,49 @@ describe('compiler specification', () => {
expect(renderComp(MyApp)).toEqual(`<button hostlistenerdir="">Click</button>`);
});
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: `
<div hostAttributeDir></div>
`
})
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(`<div hostattributedir="" role="listbox"></div>`);
});
it('should support bindings of host attributes', () => {
type $MyApp$ = MyApp;