diff --git a/packages/common/src/directives/styling_differ.ts b/packages/common/src/directives/styling_differ.ts index 9ba3552bb1..972c15337d 100644 --- a/packages/common/src/directives/styling_differ.ts +++ b/packages/common/src/directives/styling_differ.ts @@ -212,11 +212,11 @@ function bulidMapFromValues( // case 1: map for (let i = 0; i < keys.length; i++) { let key = keys[i]; - key = trim ? key.trim() : key; const value = (values as{[key: string]: any})[key]; if (value !== undefined) { - setMapValues(map, key, value, parseOutUnits, allowSubKeys); + // Map uses untrimmed keys, so don't trim until passing to `setMapValues` + setMapValues(map, trim ? key.trim() : key, value, parseOutUnits, allowSubKeys); } } } else { diff --git a/packages/core/test/acceptance/styling_spec.ts b/packages/core/test/acceptance/styling_spec.ts index 811f8db763..4addfa16e2 100644 --- a/packages/core/test/acceptance/styling_spec.ts +++ b/packages/core/test/acceptance/styling_spec.ts @@ -2485,6 +2485,28 @@ describe('styling', () => { const div = fixture.nativeElement.querySelector('div'); expect(getComputedStyle(div).width).toBe('10px'); }); + + it('should allow classes with trailing and leading spaces in [ngClass]', () => { + @Component({ + template: ` +
+ + ` + }) + class Cmp { + applyClasses = true; + } + + TestBed.configureTestingModule({declarations: [Cmp]}); + const fixture = TestBed.createComponent(Cmp); + fixture.detectChanges(); + + const leading = fixture.nativeElement.querySelector('[leading-space]'); + const trailing = fixture.nativeElement.querySelector('[trailing-space]'); + expect(leading.className).toBe('foo', 'Expected class to be applied despite leading space.'); + expect(trailing.className).toBe('foo', 'Expected class to be applied despite trailing space.'); + }); + }); function assertStyleCounters(countForSet: number, countForRemove: number) {