|
1 | | -import {isPresent, isBlank, Type, isString} from 'angular2/src/core/facade/lang'; |
| 1 | +import {isPresent, isBlank, Type, isString, StringWrapper} from 'angular2/src/core/facade/lang'; |
2 | 2 | import {SetWrapper, StringMapWrapper, ListWrapper} from 'angular2/src/core/facade/collection'; |
3 | 3 | import { |
4 | 4 | TemplateCmd, |
@@ -44,6 +44,8 @@ export var TEMPLATE_COMMANDS_MODULE_REF = |
44 | 44 | moduleRef(`package:angular2/src/core/linker/template_commands${MODULE_SUFFIX}`); |
45 | 45 |
|
46 | 46 | const IMPLICIT_TEMPLATE_VAR = '\$implicit'; |
| 47 | +const CLASS_ATTR = 'class'; |
| 48 | +const STYLE_ATTR = 'style'; |
47 | 49 |
|
48 | 50 | @Injectable() |
49 | 51 | export class CommandCompiler { |
@@ -211,14 +213,14 @@ class CommandBuilderVisitor<R> implements TemplateAstVisitor { |
211 | 213 |
|
212 | 214 | private _readAttrNameAndValues(directives: CompileDirectiveMetadata[], |
213 | 215 | attrAsts: TemplateAst[]): string[] { |
214 | | - var attrNameAndValues: string[] = visitAndReturnContext(this, attrAsts, []); |
| 216 | + var attrs = keyValueArrayToMap(visitAndReturnContext(this, attrAsts, [])); |
215 | 217 | directives.forEach(directiveMeta => { |
216 | 218 | StringMapWrapper.forEach(directiveMeta.hostAttributes, (value, name) => { |
217 | | - attrNameAndValues.push(name); |
218 | | - attrNameAndValues.push(value); |
| 219 | + var prevValue = attrs[name]; |
| 220 | + attrs[name] = isPresent(prevValue) ? mergeAttributeValue(name, prevValue, value) : value; |
219 | 221 | }); |
220 | 222 | }); |
221 | | - return removeKeyValueArrayDuplicates(attrNameAndValues); |
| 223 | + return mapToKeyValueArray(attrs); |
222 | 224 | } |
223 | 225 |
|
224 | 226 | visitNgContent(ast: NgContentAst, context: any): any { |
@@ -328,6 +330,36 @@ function removeKeyValueArrayDuplicates(keyValueArray: string[]): string[] { |
328 | 330 | return resultKeyValueArray; |
329 | 331 | } |
330 | 332 |
|
| 333 | +function keyValueArrayToMap(keyValueArr: string[]): {[key: string]: string} { |
| 334 | + var data: {[key: string]: string} = {}; |
| 335 | + for (var i = 0; i < keyValueArr.length; i += 2) { |
| 336 | + data[keyValueArr[i]] = keyValueArr[i + 1]; |
| 337 | + } |
| 338 | + return data; |
| 339 | +} |
| 340 | + |
| 341 | +function mapToKeyValueArray(data: {[key: string]: string}): string[] { |
| 342 | + var entryArray = []; |
| 343 | + StringMapWrapper.forEach(data, (value, name) => { entryArray.push([name, value]); }); |
| 344 | + // We need to sort to get a defined output order |
| 345 | + // for tests and for caching generated artifacts... |
| 346 | + ListWrapper.sort(entryArray, (entry1, entry2) => StringWrapper.compare(entry1[0], entry2[0])); |
| 347 | + var keyValueArray = []; |
| 348 | + entryArray.forEach((entry) => { |
| 349 | + keyValueArray.push(entry[0]); |
| 350 | + keyValueArray.push(entry[1]); |
| 351 | + }); |
| 352 | + return keyValueArray; |
| 353 | +} |
| 354 | + |
| 355 | +function mergeAttributeValue(attrName: string, attrValue1: string, attrValue2: string): string { |
| 356 | + if (attrName == CLASS_ATTR || attrName == STYLE_ATTR) { |
| 357 | + return `${attrValue1} ${attrValue2}`; |
| 358 | + } else { |
| 359 | + return attrValue2; |
| 360 | + } |
| 361 | +} |
| 362 | + |
331 | 363 | class DirectiveContext { |
332 | 364 | constructor(public index: number, public eventTargetAndNames: string[], |
333 | 365 | public targetVariableNameAndValues: any[], |
|
0 commit comments