fix(forms): changed forms to create only one value accessor instead of always creating DefaultValueAccessor
This commit is contained in:
		
							parent
							
								
									2ff3873881
								
							
						
					
					
						commit
						30c3e5a84e
					
				| @ -32,35 +32,6 @@ function _lookupControl(groupDirective: ControlGroupDirective, controlOrName: an | ||||
|   return control; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * The default accessor for writing a value and listening to changes that is used by a {@link | ||||
|  * Control} directive. | ||||
|  * | ||||
|  * This is the default strategy that Angular uses when no other accessor is applied. | ||||
|  * | ||||
|  *  # Example | ||||
|  *  ``` | ||||
|  *  <input type="text" [control]="loginControl"> | ||||
|  *  ``` | ||||
|  * | ||||
|  * @exportedAs angular2/forms | ||||
|  */ | ||||
| @Directive({ | ||||
|   selector: '[control]', | ||||
|   hostListeners: | ||||
|       {'change': 'onChange($event.target.value)', 'input': 'onChange($event.target.value)'}, | ||||
|   hostProperties: {'value': 'value'} | ||||
| }) | ||||
| export class DefaultValueAccessor { | ||||
|   value; | ||||
|   onChange: Function; | ||||
| 
 | ||||
|   constructor() { this.onChange = (_) => {}; } | ||||
| 
 | ||||
|   writeValue(value) { this.value = value } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Binds a control group to a DOM element. | ||||
|  * | ||||
| @ -171,11 +142,9 @@ export class ControlDirective { | ||||
| 
 | ||||
|   validator: Function; | ||||
| 
 | ||||
|   constructor(@Optional() @Ancestor() groupDirective: ControlGroupDirective, | ||||
|               valueAccessor: DefaultValueAccessor) { | ||||
|   constructor(@Optional() @Ancestor() groupDirective: ControlGroupDirective) { | ||||
|     this._groupDirective = groupDirective; | ||||
|     this._controlOrName = null; | ||||
|     this.valueAccessor = valueAccessor; | ||||
|     this.validator = Validators.nullValidator; | ||||
|   } | ||||
| 
 | ||||
| @ -189,6 +158,10 @@ export class ControlDirective { | ||||
|     var c = this._control(); | ||||
|     c.validator = Validators.compose([c.validator, this.validator]); | ||||
| 
 | ||||
|     if (isBlank(this.valueAccessor)) { | ||||
|       throw new BaseException(`Cannot find value accessor for control "${controlOrName}"`); | ||||
|     } | ||||
| 
 | ||||
|     this._updateDomValue(); | ||||
|     this._setUpUpdateControlValue(); | ||||
|   } | ||||
| @ -202,6 +175,75 @@ export class ControlDirective { | ||||
|   _control() { return _lookupControl(this._groupDirective, this._controlOrName); } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * The default accessor for writing a value and listening to changes that is used by a {@link | ||||
|   * Control} directive. | ||||
|  * | ||||
|  * This is the default strategy that Angular uses when no other accessor is applied. | ||||
|  * | ||||
|  *  # Example | ||||
|  *  ``` | ||||
|  *  <input type="text" [control]="loginControl"> | ||||
|  *  ``` | ||||
|  * | ||||
|  * @exportedAs angular2/forms | ||||
|  */ | ||||
| @Directive({ | ||||
|   selector: 'input:not([type=checkbox])[control],textarea[control]', | ||||
|   hostListeners: | ||||
|       {'change': 'onChange($event.target.value)', 'input': 'onChange($event.target.value)'}, | ||||
|   hostProperties: {'value': 'value'} | ||||
| }) | ||||
| export class DefaultValueAccessor { | ||||
|   value = null; | ||||
|   onChange: Function; | ||||
| 
 | ||||
|   constructor(cd: ControlDirective, private _elementRef: ElementRef, private _renderer: Renderer) { | ||||
|     this.onChange = (_) => {}; | ||||
|     cd.valueAccessor = this; | ||||
|   } | ||||
| 
 | ||||
|   writeValue(value) { | ||||
|     this._renderer.setElementProperty(this._elementRef.parentView.render, | ||||
|                                       this._elementRef.boundElementIndex, 'value', value) | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * The accessor for writing a value and listening to changes that is used by a {@link | ||||
|   * Control} directive. | ||||
|  * | ||||
|  * This is the default strategy that Angular uses when no other accessor is applied. | ||||
|  * | ||||
|  *  # Example | ||||
|  *  ``` | ||||
|  *  <input type="text" [control]="loginControl"> | ||||
|  *  ``` | ||||
|  * | ||||
|  * @exportedAs angular2/forms | ||||
|  */ | ||||
| @Directive({ | ||||
|   selector: 'select[control]', | ||||
|   hostListeners: | ||||
|       {'change': 'onChange($event.target.value)', 'input': 'onChange($event.target.value)'}, | ||||
|   hostProperties: {'value': 'value'} | ||||
| }) | ||||
| export class SelectControlValueAccessor { | ||||
|   value = null; | ||||
|   onChange: Function; | ||||
| 
 | ||||
|   constructor(cd: ControlDirective, private _elementRef: ElementRef, private _renderer: Renderer) { | ||||
|     this.onChange = (_) => {}; | ||||
|     this.value = ''; | ||||
|     cd.valueAccessor = this; | ||||
|   } | ||||
| 
 | ||||
|   writeValue(value) { | ||||
|     this._renderer.setElementProperty(this._elementRef.parentView.render, | ||||
|                                       this._elementRef.boundElementIndex, 'value', value) | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * The accessor for writing a value and listening to changes on a checkbox input element. | ||||
|  * | ||||
| @ -219,17 +261,12 @@ export class ControlDirective { | ||||
|   hostProperties: {'checked': 'checked'} | ||||
| }) | ||||
| export class CheckboxControlValueAccessor { | ||||
|   _elementRef: ElementRef; | ||||
|   _renderer: Renderer; | ||||
| 
 | ||||
|   checked: boolean; | ||||
|   onChange: Function; | ||||
| 
 | ||||
|   constructor(cd: ControlDirective, elementRef: ElementRef, renderer: Renderer) { | ||||
|   constructor(cd: ControlDirective, private _elementRef: ElementRef, private _renderer: Renderer) { | ||||
|     this.onChange = (_) => {}; | ||||
|     this._elementRef = elementRef; | ||||
|     this._renderer = renderer; | ||||
|     cd.valueAccessor = this;  // ControlDirective should inject CheckboxControlDirective
 | ||||
|     cd.valueAccessor = this; | ||||
|   } | ||||
| 
 | ||||
|   writeValue(value) { | ||||
| @ -246,5 +283,10 @@ export class CheckboxControlValueAccessor { | ||||
|  * | ||||
|  * @exportedAs angular2/forms | ||||
|  */ | ||||
| export const formDirectives: List<Type> = CONST_EXPR( | ||||
|     [ControlGroupDirective, ControlDirective, CheckboxControlValueAccessor, DefaultValueAccessor]); | ||||
| export const formDirectives: List<Type> = CONST_EXPR([ | ||||
|   ControlGroupDirective, | ||||
|   ControlDirective, | ||||
|   CheckboxControlValueAccessor, | ||||
|   DefaultValueAccessor, | ||||
|   SelectControlValueAccessor | ||||
| ]); | ||||
|  | ||||
| @ -6,7 +6,7 @@ export function main() { | ||||
|   describe("Form Directives", () => { | ||||
|     describe("Control", () => { | ||||
|       it("should throw when the group is not found and the control is not set", () => { | ||||
|         var c = new ControlDirective(null, null); | ||||
|         var c = new ControlDirective(null); | ||||
|         expect(() => { | ||||
|           c.controlOrName = 'login'; | ||||
|         }).toThrowError(new RegExp('No control group found for "login"')); | ||||
| @ -16,7 +16,7 @@ export function main() { | ||||
|         var emptyGroup = new ControlGroupDirective(null); | ||||
|         emptyGroup.controlOrName = new ControlGroup({}); | ||||
| 
 | ||||
|         var c = new ControlDirective(emptyGroup, null); | ||||
|         var c = new ControlDirective(emptyGroup); | ||||
|         expect(() => { | ||||
|           c.controlOrName = 'login'; | ||||
|         }).toThrowError(new RegExp('Cannot find control "login"')); | ||||
|  | ||||
							
								
								
									
										20
									
								
								modules/angular2/test/forms/integration_spec.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								modules/angular2/test/forms/integration_spec.js
									
									
									
									
										vendored
									
									
								
							| @ -21,8 +21,7 @@ import {View} from 'angular2/src/core/annotations_impl/view'; | ||||
| 
 | ||||
| import {TestBed} from 'angular2/src/test_lib/test_bed'; | ||||
| 
 | ||||
| import {ControlGroupDirective, ControlDirective, Control, ControlGroup, RequiredValidatorDirective, CheckboxControlValueAccessor, | ||||
|   DefaultValueAccessor, Validators} from 'angular2/forms'; | ||||
| import {ControlGroupDirective, ControlDirective, Control, ControlGroup, RequiredValidatorDirective, CheckboxControlValueAccessor, DefaultValueAccessor, SelectControlValueAccessor, Validators} from 'angular2/forms'; | ||||
| 
 | ||||
| export function main() { | ||||
|   describe("integration tests", () => { | ||||
| @ -266,6 +265,19 @@ export function main() { | ||||
|           async.done(); | ||||
|         }); | ||||
|       })); | ||||
| 
 | ||||
|       it("should throw when cannot find a value accessor", inject([TestBed, AsyncTestCompleter], (tb, async) => { | ||||
|         var ctx = new MyComp(new ControlGroup({"name": new Control("aa")})); | ||||
| 
 | ||||
|         var t = `<div [control-group]="form">
 | ||||
|                   <div control="name"> | ||||
|                 </div>`; | ||||
| 
 | ||||
|         tb.createView(MyComp, {context: ctx, html: t}).then((view) => { | ||||
|           expect(() => view.detectChanges()).toThrowError(new RegExp("Cannot find value accessor")) | ||||
|           async.done(); | ||||
|         }); | ||||
|       })); | ||||
|     }); | ||||
| 
 | ||||
|     describe("validations", () => { | ||||
| @ -377,7 +389,9 @@ export function main() { | ||||
|   WrappedValue, | ||||
|   RequiredValidatorDirective, | ||||
|   DefaultValueAccessor, | ||||
|   CheckboxControlValueAccessor]}) | ||||
|   CheckboxControlValueAccessor, | ||||
|   SelectControlValueAccessor | ||||
| ]}) | ||||
| class MyComp { | ||||
|   form:any; | ||||
|   name:string; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user