Skip to content

Commit

Permalink
fix(ivy): unable to bind to properties that start with class or style (
Browse files Browse the repository at this point in the history
…#32421)

Fixes Ivy picking up property bindings that start with `class` or `style` as if they're style bindings.

Fixes #32310

PR Close #32421
  • Loading branch information
crisbeto authored and matsko committed Sep 5, 2019
1 parent 098feec commit 62d92f8
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 4 deletions.
7 changes: 4 additions & 3 deletions packages/compiler/src/render3/view/styling_builder.ts
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -149,9 +149,10 @@ export class StylingBuilder {


registerInputBasedOnName(name: string, expression: AST, sourceSpan: ParseSourceSpan) { registerInputBasedOnName(name: string, expression: AST, sourceSpan: ParseSourceSpan) {
let binding: BoundStylingEntry|null = null; let binding: BoundStylingEntry|null = null;
const nameToMatch = name.substring(0, 5); // class | style const prefix = name.substring(0, 6);
const isStyle = nameToMatch === 'style'; const isStyle = name === 'style' || prefix === 'style.' || prefix === 'style!';
const isClass = isStyle ? false : (nameToMatch === 'class'); const isClass = !isStyle &&
(name === 'class' || name === 'className' || prefix === 'class.' || prefix === 'class!');
if (isStyle || isClass) { if (isStyle || isClass) {
const isMapBased = name.charAt(5) !== '.'; // style.prop or class.prop makes this a no const isMapBased = name.charAt(5) !== '.'; // style.prop or class.prop makes this a no
const property = name.substr(isMapBased ? 5 : 6); // the dot explains why there's a +1 const property = name.substr(isMapBased ? 5 : 6); // the dot explains why there's a +1
Expand Down
44 changes: 43 additions & 1 deletion packages/core/test/acceptance/styling_spec.ts
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Use of this source code is governed by an MIT-style license that can be * Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {Component, Directive, ElementRef, Input} from '@angular/core'; import {Component, Directive, ElementRef, HostBinding, Input, ViewChild} from '@angular/core';
import {ngDevModeResetPerfCounters} from '@angular/core/src/util/ng_dev_mode'; import {ngDevModeResetPerfCounters} from '@angular/core/src/util/ng_dev_mode';
import {TestBed} from '@angular/core/testing'; import {TestBed} from '@angular/core/testing';
import {By, DomSanitizer, SafeStyle} from '@angular/platform-browser'; import {By, DomSanitizer, SafeStyle} from '@angular/platform-browser';
Expand Down Expand Up @@ -631,4 +631,46 @@ describe('styling', () => {


}); });
}); });

it('should be able to name inputs starting with `class` or `style`', () => {
@Directive({selector: '[dir]'})
class Dir {
@Input('classesInSchool') classes = '';
@Input('styleOfClothing') style = '';
}

@Component({
template: '<span dir [classesInSchool]="classes" [styleOfClothing]="style"></span>',
})
class App {
@ViewChild(Dir, {static: false}) dir !: Dir;

classes = 'math';
style = '80s';
}

TestBed.configureTestingModule({declarations: [App, Dir]});
const fixture = TestBed.createComponent(App);
fixture.detectChanges();
const directive = fixture.componentInstance.dir;

expect(directive.classes).toBe('math');
expect(directive.style).toBe('80s');
});

it('should be able to bind to `className`', () => {
@Component({template: ''})
class App {
@HostBinding('className')
klass = 'one two';
}

TestBed.configureTestingModule({declarations: [App]});
const fixture = TestBed.createComponent(App);
fixture.detectChanges();
const classList = fixture.nativeElement.classList;

expect(classList.contains('one')).toBe(true);
expect(classList.contains('two')).toBe(true);
});
}); });

0 comments on commit 62d92f8

Please sign in to comment.