fix(ivy): handling className as an input properly (#33188)

Prior to this commit, all `className` inputs were not set because the runtime code assumed that the `classMap` instruction is only generated for `[class]` bindings. However the `[className]` binding also produces the same `classMap`, thus the code needs to distinguish between `class` and `className`. This commit adds extra logic to select the right input name and also throws an error in case `[class]` and `[className]` bindings are used on the same element simultaneously.

PR Close #33188
This commit is contained in:
Andrew Kushnir
2019-10-04 19:25:18 -07:00
committed by Matias Niemelä
parent 08cb2fa80f
commit 6f203c9575
8 changed files with 91 additions and 6 deletions

View File

@ -551,6 +551,74 @@ describe('styling', () => {
expect(capturedMyClassBindingCount).toEqual(1);
});
it('should write to a `className` input binding', () => {
@Component({
selector: 'comp',
template: `{{className}}`,
})
class Comp {
@Input() className: string = '';
}
@Component({
template: `<comp [className]="'my-className'"></comp>`,
})
class App {
}
TestBed.configureTestingModule({declarations: [Comp, App]});
const fixture = TestBed.createComponent(App);
fixture.detectChanges();
expect(fixture.debugElement.nativeElement.firstChild.innerHTML).toBe('my-className');
});
onlyInIvy('only ivy combines static and dynamic class-related attr values')
.it('should write to a `className` input binding, when static `class` is present', () => {
@Component({
selector: 'comp',
template: `{{className}}`,
})
class Comp {
@Input() className: string = '';
}
@Component({
template: `<comp class="static" [className]="'my-className'"></comp>`,
})
class App {
}
TestBed.configureTestingModule({declarations: [Comp, App]});
const fixture = TestBed.createComponent(App);
fixture.detectChanges();
expect(fixture.debugElement.nativeElement.firstChild.innerHTML).toBe('static my-className');
});
onlyInIvy('in Ivy [class] and [className] bindings on the same element are not allowed')
.it('should throw an error in case [class] and [className] bindings are used on the same element',
() => {
@Component({
selector: 'comp',
template: `{{class}} - {{className}}`,
})
class Comp {
@Input() class: string = '';
@Input() className: string = '';
}
@Component({
template: `<comp [class]="'my-class'" [className]="'className'"></comp>`,
})
class App {
}
TestBed.configureTestingModule({declarations: [Comp, App]});
expect(() => {
const fixture = TestBed.createComponent(App);
fixture.detectChanges();
})
.toThrowError(
'[class] and [className] bindings cannot be used on the same element simultaneously');
});
onlyInIvy('only ivy persists static class/style attrs with their binding counterparts')
.it('should write to a `class` input binding if there is a static class value and there is a binding value',
() => {