feat(compiler): added support for [()] syntax
This commit is contained in:
		
							parent
							
								
									846354473d
								
							
						
					
					
						commit
						685a6507b6
					
				
							
								
								
									
										2
									
								
								modules/angular2/src/core/compiler/view.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								modules/angular2/src/core/compiler/view.js
									
									
									
									
										vendored
									
									
								
							| @ -151,7 +151,7 @@ export class AppView { | |||||||
|         } |         } | ||||||
|         var result = expr.eval(context, new Locals(this.locals, locals)); |         var result = expr.eval(context, new Locals(this.locals, locals)); | ||||||
|         if (isPresent(result)) { |         if (isPresent(result)) { | ||||||
|           allowDefaultBehavior = allowDefaultBehavior && result; |           allowDefaultBehavior = allowDefaultBehavior && result == true; | ||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -12,12 +12,13 @@ import {dashCaseToCamelCase} from '../util'; | |||||||
| // Group 1 = "bind-"
 | // Group 1 = "bind-"
 | ||||||
| // Group 2 = "var-" or "#"
 | // Group 2 = "var-" or "#"
 | ||||||
| // Group 3 = "on-"
 | // Group 3 = "on-"
 | ||||||
| // Group 4 = the identifier after "bind-", "var-/#", or "on-"
 | // Group 4 = "bindon-"
 | ||||||
| // Group 5 = idenitifer inside square braces
 | // Group 5 = the identifier after "bind-", "var-/#", or "on-"
 | ||||||
| // Group 6 = identifier inside parenthesis
 | // Group 6 = idenitifer inside [()]
 | ||||||
|  | // Group 7 = idenitifer inside []
 | ||||||
|  | // Group 8 = identifier inside ()
 | ||||||
| var BIND_NAME_REGEXP = RegExpWrapper.create( | var BIND_NAME_REGEXP = RegExpWrapper.create( | ||||||
|     '^(?:(?:(?:(bind-)|(var-|#)|(on-))(.+))|\\[([^\\]]+)\\]|\\(([^\\)]+)\\))$'); |     '^(?:(?:(?:(bind-)|(var-|#)|(on-)|(bindon-))(.+))|\\[\\(([^\\)]+)\\)\\]|\\[([^\\]]+)\\]|\\(([^\\)]+)\\))$'); | ||||||
| 
 |  | ||||||
| /** | /** | ||||||
|  * Parses the property bindings on a single element. |  * Parses the property bindings on a single element. | ||||||
|  */ |  */ | ||||||
| @ -36,23 +37,30 @@ export class PropertyBindingParser extends CompileStep { | |||||||
|     MapWrapper.forEach(attrs, (attrValue, attrName) => { |     MapWrapper.forEach(attrs, (attrValue, attrName) => { | ||||||
|       var bindParts = RegExpWrapper.firstMatch(BIND_NAME_REGEXP, attrName); |       var bindParts = RegExpWrapper.firstMatch(BIND_NAME_REGEXP, attrName); | ||||||
|       if (isPresent(bindParts)) { |       if (isPresent(bindParts)) { | ||||||
|         if (isPresent(bindParts[1])) { |         if (isPresent(bindParts[1])) { // match: bind-prop
 | ||||||
|           // match: bind-prop
 |           this._bindProperty(bindParts[5], attrValue, current, newAttrs); | ||||||
|           this._bindProperty(bindParts[4], attrValue, current, newAttrs); | 
 | ||||||
|         } else if (isPresent(bindParts[2])) { |         } else if (isPresent(bindParts[2])) { // match: var-name / var-name="iden" / #name / #name="iden"
 | ||||||
|           // match: var-name / var-name="iden" / #name / #name="iden"
 |           var identifier = bindParts[5]; | ||||||
|           var identifier = bindParts[4]; |  | ||||||
|           var value = attrValue == '' ? '\$implicit' : attrValue; |           var value = attrValue == '' ? '\$implicit' : attrValue; | ||||||
|           this._bindVariable(identifier, value, current, newAttrs); |           this._bindVariable(identifier, value, current, newAttrs); | ||||||
|         } else if (isPresent(bindParts[3])) { | 
 | ||||||
|           // match: on-event
 |         } else if (isPresent(bindParts[3])) { // match: on-event
 | ||||||
|           this._bindEvent(bindParts[4], attrValue, current, newAttrs); |           this._bindEvent(bindParts[5], attrValue, current, newAttrs); | ||||||
|         } else if (isPresent(bindParts[5])) { | 
 | ||||||
|           // match: [prop]
 |         } else if (isPresent(bindParts[4])) { // match: bindon-prop
 | ||||||
|           this._bindProperty(bindParts[5], attrValue, current, newAttrs); |           this._bindProperty(bindParts[5], attrValue, current, newAttrs); | ||||||
|         } else if (isPresent(bindParts[6])) { |           this._bindAssignmentEvent(bindParts[5], attrValue, current, newAttrs); | ||||||
|           // match: (event)
 | 
 | ||||||
|           this._bindEvent(bindParts[6], attrValue, current, newAttrs); |         } else if (isPresent(bindParts[6])) { // match: [(expr)]
 | ||||||
|  |           this._bindProperty(bindParts[6], attrValue, current, newAttrs); | ||||||
|  |           this._bindAssignmentEvent(bindParts[6], attrValue, current, newAttrs); | ||||||
|  | 
 | ||||||
|  |         } else if (isPresent(bindParts[7])) { // match: [expr]
 | ||||||
|  |           this._bindProperty(bindParts[7], attrValue, current, newAttrs); | ||||||
|  | 
 | ||||||
|  |         } else if (isPresent(bindParts[8])) { // match: (event)
 | ||||||
|  |           this._bindEvent(bindParts[8], attrValue, current, newAttrs); | ||||||
|         } |         } | ||||||
|       } else { |       } else { | ||||||
|         var expr = this._parser.parseInterpolation( |         var expr = this._parser.parseInterpolation( | ||||||
| @ -90,6 +98,10 @@ export class PropertyBindingParser extends CompileStep { | |||||||
|     MapWrapper.set(newAttrs, name, ast.source); |     MapWrapper.set(newAttrs, name, ast.source); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   _bindAssignmentEvent(name, expression, current:CompileElement, newAttrs) { | ||||||
|  |     this._bindEvent(name, `${expression}=$event`, current, newAttrs); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   _bindEvent(name, expression, current:CompileElement, newAttrs) { |   _bindEvent(name, expression, current:CompileElement, newAttrs) { | ||||||
|     current.bindElement().bindEvent( |     current.bindElement().bindEvent( | ||||||
|       dashCaseToCamelCase(name), this._parser.parseAction(expression, current.elementDescription) |       dashCaseToCamelCase(name), this._parser.parseAction(expression, current.elementDescription) | ||||||
|  | |||||||
| @ -603,6 +603,30 @@ export function main() { | |||||||
|         }); |         }); | ||||||
|       })); |       })); | ||||||
| 
 | 
 | ||||||
|  |       it('should support [()] syntax', inject([TestBed, AsyncTestCompleter], (tb, async) => { | ||||||
|  |         tb.overrideView(MyComp, new View({ | ||||||
|  |           template: '<div [(control)]="ctxProp" two-way></div>', | ||||||
|  |           directives: [DirectiveWithTwoWayBinding] | ||||||
|  |         })); | ||||||
|  | 
 | ||||||
|  |         tb.createView(MyComp, {context: ctx}).then((view) => { | ||||||
|  |           var injector = view.rawView.elementInjectors[0]; | ||||||
|  |           var dir = injector.get(DirectiveWithTwoWayBinding); | ||||||
|  | 
 | ||||||
|  |           ctx.ctxProp = 'one'; | ||||||
|  |           view.detectChanges(); | ||||||
|  | 
 | ||||||
|  |           expect(dir.value).toEqual('one'); | ||||||
|  | 
 | ||||||
|  |           ObservableWrapper.subscribe(dir.control, (_) => { | ||||||
|  |             expect(ctx.ctxProp).toEqual('two'); | ||||||
|  |             async.done(); | ||||||
|  |           }); | ||||||
|  | 
 | ||||||
|  |           dir.triggerChange('two'); | ||||||
|  |         }); | ||||||
|  |       })); | ||||||
|  | 
 | ||||||
|       if (DOM.supportsDOMEvents()) { |       if (DOM.supportsDOMEvents()) { | ||||||
|         it("should support invoking methods on the host element via hostActions", inject([TestBed, AsyncTestCompleter], (tb, async) => { |         it("should support invoking methods on the host element via hostActions", inject([TestBed, AsyncTestCompleter], (tb, async) => { | ||||||
|           tb.overrideView(MyComp, new View({ |           tb.overrideView(MyComp, new View({ | ||||||
| @ -1529,3 +1553,21 @@ class ToolbarComponent { | |||||||
|     this.query = query; |     this.query = query; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | @Directive({ | ||||||
|  |   selector: '[two-way]', | ||||||
|  |   properties: {value: 'control'}, | ||||||
|  |   events: ['control'] | ||||||
|  | }) | ||||||
|  | class DirectiveWithTwoWayBinding { | ||||||
|  |   control:EventEmitter; | ||||||
|  |   value:any; | ||||||
|  | 
 | ||||||
|  |   constructor() { | ||||||
|  |     this.control = new EventEmitter(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   triggerChange(value) { | ||||||
|  |     ObservableWrapper.callNext(this.control, value); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | |||||||
| @ -149,6 +149,18 @@ export function main() { | |||||||
|       expect(MapWrapper.get(results[0].attrs(), 'a')).toEqual('b'); |       expect(MapWrapper.get(results[0].attrs(), 'a')).toEqual('b'); | ||||||
|       expect(MapWrapper.get(results[0].attrs(), 'c')).toEqual('d'); |       expect(MapWrapper.get(results[0].attrs(), 'c')).toEqual('d'); | ||||||
|     }); |     }); | ||||||
|  | 
 | ||||||
|  |     it('should detect [()] syntax', () => { | ||||||
|  |       var results = process(el('<div [(a)]="b"></div>')); | ||||||
|  |       expect(MapWrapper.get(results[0].propertyBindings, 'a').source).toEqual('b'); | ||||||
|  |       expect(results[0].eventBindings[0].source.source).toEqual('b=$event'); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     it('should detect bindon- syntax', () => { | ||||||
|  |       var results = process(el('<div bindon-a="b"></div>')); | ||||||
|  |       expect(MapWrapper.get(results[0].propertyBindings, 'a').source).toEqual('b'); | ||||||
|  |       expect(results[0].eventBindings[0].source.source).toEqual('b=$event'); | ||||||
|  |     }); | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user