fix(ivy): host bindings and listeners not being inherited from undecorated classes (#30158)
Fixes `HostBinding` and `HostListener` declarations not being inherited from base classes that don't have an Angular decorator. This PR resolves FW-1275. PR Close #30158
This commit is contained in:

committed by
Andrew Kushnir

parent
164d160b22
commit
68ff2cc323
@ -3220,6 +3220,89 @@ describe('compiler compliance', () => {
|
||||
expectEmit(result.source, expectedOutput, 'Invalid base definition');
|
||||
});
|
||||
|
||||
it('should add ngBaseDef if a host binding is present', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, NgModule, HostBinding} from '@angular/core';
|
||||
export class BaseClass {
|
||||
@HostBinding('attr.tabindex')
|
||||
tabindex = -1;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: ''
|
||||
})
|
||||
export class MyComponent extends BaseClass {
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [MyComponent]
|
||||
})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
const expectedOutput = `
|
||||
// ...
|
||||
BaseClass.ngBaseDef = $r3$.ɵɵdefineBase({
|
||||
hostBindings: function (rf, ctx, elIndex) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵɵallocHostVars(1);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵelementAttribute(elIndex, "tabindex", $r3$.ɵɵbind(ctx.tabindex));
|
||||
}
|
||||
}
|
||||
});
|
||||
// ...
|
||||
`;
|
||||
const result = compile(files, angularFiles);
|
||||
expectEmit(result.source, expectedOutput, 'Invalid base definition');
|
||||
});
|
||||
|
||||
it('should add ngBaseDef if a host listener is present', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, NgModule, HostListener} from '@angular/core';
|
||||
export class BaseClass {
|
||||
@HostListener('mousedown', ['$event'])
|
||||
handleMousedown(event: any) {}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: ''
|
||||
})
|
||||
export class MyComponent extends BaseClass {
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [MyComponent]
|
||||
})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
const expectedOutput = `
|
||||
// ...
|
||||
BaseClass.ngBaseDef = $r3$.ɵɵdefineBase({
|
||||
hostBindings: function (rf, ctx, elIndex) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵɵlistener("mousedown", function ($event) {
|
||||
return ctx.handleMousedown($event);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
// ...
|
||||
`;
|
||||
const result = compile(files, angularFiles);
|
||||
expectEmit(result.source, expectedOutput, 'Invalid base definition');
|
||||
});
|
||||
|
||||
it('should NOT add ngBaseDef if @Component is present', () => {
|
||||
const files = {
|
||||
app: {
|
||||
|
@ -1723,7 +1723,7 @@ describe('ngtsc behavioral tests', () => {
|
||||
.toContain('Cannot have a pipe in an action expression');
|
||||
});
|
||||
|
||||
it('should throw in case pipes are used in host listeners', () => {
|
||||
it('should throw in case pipes are used in host bindings', () => {
|
||||
env.tsconfig();
|
||||
env.write(`test.ts`, `
|
||||
import {Component} from '@angular/core';
|
||||
|
Reference in New Issue
Block a user