fix(compiler): support directive inputs with interpolations on <ng-template>s (#35984)

Prior to this commit, Ivy compiler didn't handle directive inputs with interpolations located on `<ng-template>` elements (e.g. `<ng-template dir="{{ field }}">`). That was the case for regular inputs as well as inputs that should be processed via i18n subsystem (e.g. `<ng-template i18n-dir dir="Hello {{ name }}">`). This commit adds support for such expressions for explicit `<ng-template>`s as well as a number of tests to confirm the behavior.

Fixes #35752.

PR Close #35984
This commit is contained in:
Andrew Kushnir
2020-03-09 21:49:02 -07:00
parent 3fa895298d
commit 79659ee5aa
5 changed files with 323 additions and 12 deletions

View File

@ -341,6 +341,78 @@ describe('directives', () => {
});
describe('inputs', () => {
it('should allow directive inputs (as a prop binding) on <ng-template>', () => {
let dirInstance: WithInput;
@Directive({selector: '[dir]'})
class WithInput {
constructor() { dirInstance = this; }
@Input() dir: string = '';
}
@Component({
selector: 'my-app',
template: '<ng-template [dir]="message"></ng-template>',
})
class TestComp {
message = 'Hello';
}
TestBed.configureTestingModule({declarations: [TestComp, WithInput]});
const fixture = TestBed.createComponent(TestComp);
fixture.detectChanges();
expect(dirInstance !.dir).toBe('Hello');
});
it('should allow directive inputs (as an interpolated prop) on <ng-template>', () => {
let dirInstance: WithInput;
@Directive({selector: '[dir]'})
class WithInput {
constructor() { dirInstance = this; }
@Input() dir: string = '';
}
@Component({
selector: 'my-app',
template: '<ng-template dir="{{ message }}"></ng-template>',
})
class TestComp {
message = 'Hello';
}
TestBed.configureTestingModule({declarations: [TestComp, WithInput]});
const fixture = TestBed.createComponent(TestComp);
fixture.detectChanges();
expect(dirInstance !.dir).toBe('Hello');
});
it('should allow directive inputs (as an interpolated prop) on <ng-template> with structural directives',
() => {
let dirInstance: WithInput;
@Directive({selector: '[dir]'})
class WithInput {
constructor() { dirInstance = this; }
@Input() dir: string = '';
}
@Component({
selector: 'my-app',
template: '<ng-template *ngIf="true" dir="{{ message }}"></ng-template>',
})
class TestComp {
message = 'Hello';
}
TestBed.configureTestingModule({declarations: [TestComp, WithInput]});
const fixture = TestBed.createComponent(TestComp);
fixture.detectChanges();
expect(dirInstance !.dir).toBe('Hello');
});
});
describe('outputs', () => {
@Directive({selector: '[out]'})
class TestDir {

View File

@ -1423,6 +1423,58 @@ onlyInIvy('Ivy i18n logic').describe('runtime i18n', () => {
expect(titleDirInstances[0].title).toBe('Bonjour');
});
it('should allow directive inputs (as an interpolated prop) on <ng-template>', () => {
loadTranslations({[computeMsgId('Hello {$INTERPOLATION}')]: 'Bonjour {$INTERPOLATION}'});
let dirInstance: WithInput;
@Directive({selector: '[dir]'})
class WithInput {
constructor() { dirInstance = this; }
@Input() dir: string = '';
}
@Component({
selector: 'my-app',
template: '<ng-template i18n-dir dir="Hello {{ name }}"></ng-template>',
})
class TestComp {
name = 'Angular';
}
TestBed.configureTestingModule({declarations: [TestComp, WithInput]});
const fixture = TestBed.createComponent(TestComp);
fixture.detectChanges();
expect(dirInstance !.dir).toBe('Bonjour Angular');
});
it('should allow directive inputs (as interpolated props)' +
'on <ng-template> with structural directives present',
() => {
loadTranslations({[computeMsgId('Hello {$INTERPOLATION}')]: 'Bonjour {$INTERPOLATION}'});
let dirInstance: WithInput;
@Directive({selector: '[dir]'})
class WithInput {
constructor() { dirInstance = this; }
@Input() dir: string = '';
}
@Component({
selector: 'my-app',
template: '<ng-template *ngIf="true" i18n-dir dir="Hello {{ name }}"></ng-template>',
})
class TestComp {
name = 'Angular';
}
TestBed.configureTestingModule({declarations: [TestComp, WithInput]});
const fixture = TestBed.createComponent(TestComp);
fixture.detectChanges();
expect(dirInstance !.dir).toBe('Bonjour Angular');
});
it('should apply i18n attributes during second template pass', () => {
loadTranslations({[computeMsgId('Set')]: 'Set'});
@Directive({