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"'));
|
||||
|
|
|
@ -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…
Reference in New Issue