fix(ivy): compiler should generate bindings to host attrs properly (#26973)
PR Close #26973
This commit is contained in:
@ -559,87 +559,6 @@ describe('compiler compliance', () => {
|
||||
expectEmit(source, OtherDirectiveDefinition, 'Incorrect OtherDirective.ngDirectiveDef');
|
||||
});
|
||||
|
||||
it('should support host bindings', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Directive, HostBinding, NgModule} from '@angular/core';
|
||||
|
||||
@Directive({selector: '[hostBindingDir]'})
|
||||
export class HostBindingDir {
|
||||
@HostBinding('id') dirId = 'some id';
|
||||
}
|
||||
|
||||
@NgModule({declarations: [HostBindingDir]})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
const HostBindingDirDeclaration = `
|
||||
HostBindingDir.ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: HostBindingDir,
|
||||
selectors: [["", "hostBindingDir", ""]],
|
||||
factory: function HostBindingDir_Factory(t) { return new (t || HostBindingDir)(); },
|
||||
hostBindings: function HostBindingDir_HostBindings(dirIndex, elIndex) {
|
||||
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵload(dirIndex).dirId));
|
||||
},
|
||||
hostVars: 1
|
||||
});
|
||||
`;
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
const source = result.source;
|
||||
|
||||
expectEmit(source, HostBindingDirDeclaration, 'Invalid host binding code');
|
||||
});
|
||||
|
||||
it('should support host bindings with pure functions', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'host-binding-comp',
|
||||
host: {
|
||||
'[id]': '["red", id]'
|
||||
},
|
||||
template: ''
|
||||
})
|
||||
export class HostBindingComp {
|
||||
id = 'some id';
|
||||
}
|
||||
|
||||
@NgModule({declarations: [HostBindingComp]})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
const HostBindingCompDeclaration = `
|
||||
const $ff$ = function ($v$) { return ["red", $v$]; };
|
||||
…
|
||||
HostBindingComp.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: HostBindingComp,
|
||||
selectors: [["host-binding-comp"]],
|
||||
factory: function HostBindingComp_Factory(t) { return new (t || HostBindingComp)(); },
|
||||
hostBindings: function HostBindingComp_HostBindings(dirIndex, elIndex) {
|
||||
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵpureFunction1(1, $ff$, $r3$.ɵload(dirIndex).id)));
|
||||
},
|
||||
hostVars: 3,
|
||||
consts: 0,
|
||||
vars: 0,
|
||||
template: function HostBindingComp_Template(rf, ctx) {}
|
||||
});
|
||||
`;
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
const source = result.source;
|
||||
|
||||
expectEmit(source, HostBindingCompDeclaration, 'Invalid host binding code');
|
||||
});
|
||||
|
||||
it('should not treat ElementRef, ViewContainerRef, or ChangeDetectorRef specially when injecting',
|
||||
() => {
|
||||
const files = {
|
||||
|
@ -122,6 +122,166 @@ describe('compiler compliance: bindings', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('host bindings', () => {
|
||||
it('should support host bindings', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Directive, HostBinding, NgModule} from '@angular/core';
|
||||
|
||||
@Directive({selector: '[hostBindingDir]'})
|
||||
export class HostBindingDir {
|
||||
@HostBinding('id') dirId = 'some id';
|
||||
}
|
||||
|
||||
@NgModule({declarations: [HostBindingDir]})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
const HostBindingDirDeclaration = `
|
||||
HostBindingDir.ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: HostBindingDir,
|
||||
selectors: [["", "hostBindingDir", ""]],
|
||||
factory: function HostBindingDir_Factory(t) { return new (t || HostBindingDir)(); },
|
||||
hostBindings: function HostBindingDir_HostBindings(dirIndex, elIndex) {
|
||||
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵload(dirIndex).dirId));
|
||||
},
|
||||
hostVars: 1
|
||||
});
|
||||
`;
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
const source = result.source;
|
||||
|
||||
expectEmit(source, HostBindingDirDeclaration, 'Invalid host binding code');
|
||||
});
|
||||
|
||||
it('should support host bindings with pure functions', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'host-binding-comp',
|
||||
host: {
|
||||
'[id]': '["red", id]'
|
||||
},
|
||||
template: ''
|
||||
})
|
||||
export class HostBindingComp {
|
||||
id = 'some id';
|
||||
}
|
||||
|
||||
@NgModule({declarations: [HostBindingComp]})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
const HostBindingCompDeclaration = `
|
||||
const $ff$ = function ($v$) { return ["red", $v$]; };
|
||||
…
|
||||
HostBindingComp.ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: HostBindingComp,
|
||||
selectors: [["host-binding-comp"]],
|
||||
factory: function HostBindingComp_Factory(t) { return new (t || HostBindingComp)(); },
|
||||
hostBindings: function HostBindingComp_HostBindings(dirIndex, elIndex) {
|
||||
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵpureFunction1(1, $ff$, $r3$.ɵload(dirIndex).id)));
|
||||
},
|
||||
hostVars: 3,
|
||||
consts: 0,
|
||||
vars: 0,
|
||||
template: function HostBindingComp_Template(rf, ctx) {}
|
||||
});
|
||||
`;
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
const source = result.source;
|
||||
|
||||
expectEmit(source, HostBindingCompDeclaration, 'Invalid host binding code');
|
||||
});
|
||||
|
||||
it('should support host attribute bindings', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Directive, NgModule} from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[hostAttributeDir]',
|
||||
host: {
|
||||
'[attr.required]': 'required'
|
||||
}
|
||||
})
|
||||
export class HostAttributeDir {
|
||||
required = true;
|
||||
}
|
||||
|
||||
@NgModule({declarations: [HostAttributeDir]})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
const HostAttributeDirDeclaration = `
|
||||
HostAttributeDir.ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: HostAttributeDir,
|
||||
selectors: [["", "hostAttributeDir", ""]],
|
||||
factory: function HostAttributeDir_Factory(t) { return new (t || HostAttributeDir)(); },
|
||||
hostBindings: function HostAttributeDir_HostBindings(dirIndex, elIndex) {
|
||||
$r3$.ɵelementAttribute(elIndex, "required", $r3$.ɵbind($r3$.ɵload(dirIndex).required));
|
||||
},
|
||||
hostVars: 1
|
||||
});
|
||||
`;
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
const source = result.source;
|
||||
|
||||
expectEmit(source, HostAttributeDirDeclaration, 'Invalid host attribute code');
|
||||
});
|
||||
|
||||
it('should support host attributes', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Directive, NgModule} from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[hostAttributeDir]',
|
||||
host: {
|
||||
'aria-label': 'label'
|
||||
}
|
||||
})
|
||||
export class HostAttributeDir {
|
||||
}
|
||||
|
||||
@NgModule({declarations: [HostAttributeDir]})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
const HostAttributeDirDeclaration = `
|
||||
HostAttributeDir.ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: HostAttributeDir,
|
||||
selectors: [["", "hostAttributeDir", ""]],
|
||||
factory: function HostAttributeDir_Factory(t) { return new (t || HostAttributeDir)(); },
|
||||
attributes: ["aria-label", "label"]
|
||||
});
|
||||
`;
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
const source = result.source;
|
||||
|
||||
expectEmit(source, HostAttributeDirDeclaration, 'Invalid host attribute code');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('non bindable behavior', () => {
|
||||
const getAppFiles = (template: string = ''): MockDirectory => ({
|
||||
app: {
|
||||
|
@ -477,7 +477,7 @@ describe('ngtsc behavioral tests', () => {
|
||||
env.driveMain();
|
||||
const jsContents = env.getContents('test.js');
|
||||
expect(jsContents)
|
||||
.toContain(`i0.ɵelementProperty(elIndex, "attr.hello", i0.ɵbind(i0.ɵload(dirIndex).foo));`);
|
||||
.toContain(`i0.ɵelementAttribute(elIndex, "hello", i0.ɵbind(i0.ɵload(dirIndex).foo));`);
|
||||
expect(jsContents)
|
||||
.toContain(`i0.ɵelementProperty(elIndex, "prop", i0.ɵbind(i0.ɵload(dirIndex).bar));`);
|
||||
expect(jsContents)
|
||||
|
Reference in New Issue
Block a user