From a7a1851c0f0a416fb7ccbf4c8a3f29bd431f992a Mon Sep 17 00:00:00 2001 From: Pawel Kozlowski Date: Wed, 12 Aug 2015 10:44:46 +0200 Subject: [PATCH] feat(compiler): allow binding to className using class alias Closes #2364 --- modules/angular2/src/dom/browser_adapter.dart | 1 + modules/angular2/src/dom/browser_adapter.ts | 7 ++++++- modules/angular2/src/dom/parse5_adapter.ts | 3 +++ .../test/core/compiler/integration_spec.ts | 20 +++++++++++++++++++ .../dom/view/proto_view_builder_spec.ts | 6 ++++++ 5 files changed, 36 insertions(+), 1 deletion(-) diff --git a/modules/angular2/src/dom/browser_adapter.dart b/modules/angular2/src/dom/browser_adapter.dart index ed8b432a7346fb..a9877015c63a4f 100644 --- a/modules/angular2/src/dom/browser_adapter.dart +++ b/modules/angular2/src/dom/browser_adapter.dart @@ -157,6 +157,7 @@ class BrowserDomAdapter extends GenericBrowserDomAdapter { @override Map get attrToPropMap => const { + 'class': 'className', 'innerHtml': 'innerHTML', 'readonly': 'readOnly', 'tabindex': 'tabIndex', diff --git a/modules/angular2/src/dom/browser_adapter.ts b/modules/angular2/src/dom/browser_adapter.ts index a9c7a5d7b5df23..6bc55fce6ac6fe 100644 --- a/modules/angular2/src/dom/browser_adapter.ts +++ b/modules/angular2/src/dom/browser_adapter.ts @@ -3,7 +3,12 @@ import {isBlank, isPresent, global} from 'angular2/src/facade/lang'; import {setRootDomAdapter} from './dom_adapter'; import {GenericBrowserDomAdapter} from './generic_browser_adapter'; -var _attrToPropMap = {'innerHtml': 'innerHTML', 'readonly': 'readOnly', 'tabindex': 'tabIndex'}; +var _attrToPropMap = { + 'class': 'className', + 'innerHtml': 'innerHTML', + 'readonly': 'readOnly', + 'tabindex': 'tabIndex' +}; const DOM_KEY_LOCATION_NUMPAD = 3; diff --git a/modules/angular2/src/dom/parse5_adapter.ts b/modules/angular2/src/dom/parse5_adapter.ts index 945c505e886297..7f9c3a40c8d531 100644 --- a/modules/angular2/src/dom/parse5_adapter.ts +++ b/modules/angular2/src/dom/parse5_adapter.ts @@ -13,6 +13,7 @@ import {BaseException, isPresent, isBlank, global} from 'angular2/src/facade/lan import {SelectorMatcher, CssSelector} from 'angular2/src/render/dom/compiler/selector'; var _attrToPropMap = { + 'class': 'className', 'innerHtml': 'innerHTML', 'readonly': 'readOnly', 'tabindex': 'tabIndex', @@ -37,6 +38,8 @@ export class Parse5DomAdapter extends DomAdapter { setProperty(el: /*element*/ any, name: string, value: any) { if (name === 'innerHTML') { this.setInnerHTML(el, value); + } else if (name === 'className') { + el.attribs["class"] = el.className = value; } else { el[name] = value; } diff --git a/modules/angular2/test/core/compiler/integration_spec.ts b/modules/angular2/test/core/compiler/integration_spec.ts index b041c810aa551c..f9acb04764c6d0 100644 --- a/modules/angular2/test/core/compiler/integration_spec.ts +++ b/modules/angular2/test/core/compiler/integration_spec.ts @@ -212,6 +212,26 @@ export function main() { }); })); + it('should consume binding to className using class alias', + inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { + tcb.overrideView( + MyComp, + new viewAnn.View({template: '
'})) + + .createAsync(MyComp) + .then((rootTC) => { + var nativeEl = rootTC.componentViewChildren[0].nativeElement; + rootTC.componentInstance.ctxProp = 'foo bar'; + rootTC.detectChanges(); + + expect(nativeEl).toHaveCssClass('foo'); + expect(nativeEl).toHaveCssClass('bar'); + expect(nativeEl).not.toHaveCssClass('initial'); + + async.done(); + }); + })); + it('should consume directive watch expression change.', inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { var tpl = '
' + diff --git a/modules/angular2/test/render/dom/view/proto_view_builder_spec.ts b/modules/angular2/test/render/dom/view/proto_view_builder_spec.ts index 913cff5b0e6fba..9ba61e31ed32d7 100644 --- a/modules/angular2/test/render/dom/view/proto_view_builder_spec.ts +++ b/modules/angular2/test/render/dom/view/proto_view_builder_spec.ts @@ -104,6 +104,12 @@ export function main() { var pv = builder.build(new DomElementSchemaRegistry(), templateCloner); expect(pv.elementBinders[0].propertyBindings[0].property).toEqual('readOnly'); }); + + it('should normalize "class" to "className"', () => { + builder.bindElement(el('
')).bindProperty('class', emptyExpr()); + var pv = builder.build(new DomElementSchemaRegistry(), templateCloner); + expect(pv.elementBinders[0].propertyBindings[0].property).toEqual('className'); + }); }); describe('property binding', () => {