feat(forms): support adding validators to ControlGroup via template
Closes #4954
This commit is contained in:
@ -21,4 +21,6 @@ export class AbstractControlDirective {
|
||||
get touched(): boolean { return isPresent(this.control) ? this.control.touched : null; }
|
||||
|
||||
get untouched(): boolean { return isPresent(this.control) ? this.control.untouched : null; }
|
||||
|
||||
get path(): string[] { return null; }
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ export class NgControl extends AbstractControlDirective {
|
||||
valueAccessor: ControlValueAccessor = null;
|
||||
|
||||
get validator(): Function { return null; }
|
||||
get path(): string[] { return null; }
|
||||
|
||||
viewToModelUpdate(newValue: any): void {}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import {OnInit, OnDestroy} from 'angular2/lifecycle_hooks';
|
||||
import {Directive} from 'angular2/src/core/metadata';
|
||||
import {Inject, Host, SkipSelf, forwardRef, Provider} from 'angular2/src/core/di';
|
||||
import {Optional, Inject, Host, SkipSelf, forwardRef, Provider} from 'angular2/src/core/di';
|
||||
import {ListWrapper} from 'angular2/src/core/facade/collection';
|
||||
import {CONST_EXPR} from 'angular2/src/core/facade/lang';
|
||||
|
||||
@ -8,6 +8,7 @@ import {ControlContainer} from './control_container';
|
||||
import {controlPath} from './shared';
|
||||
import {ControlGroup} from '../model';
|
||||
import {Form} from './form_interface';
|
||||
import {Validators, NG_VALIDATORS} from '../validators';
|
||||
|
||||
const controlGroupBinding =
|
||||
CONST_EXPR(new Provider(ControlContainer, {useExisting: forwardRef(() => NgControlGroup)}));
|
||||
@ -60,9 +61,14 @@ export class NgControlGroup extends ControlContainer implements OnInit,
|
||||
OnDestroy {
|
||||
/** @internal */
|
||||
_parent: ControlContainer;
|
||||
constructor(@Host() @SkipSelf() _parent: ControlContainer) {
|
||||
|
||||
private _validators: Function[];
|
||||
|
||||
constructor(@Host() @SkipSelf() parent: ControlContainer,
|
||||
@Optional() @Inject(NG_VALIDATORS) validators: Function[]) {
|
||||
super();
|
||||
this._parent = _parent;
|
||||
this._parent = parent;
|
||||
this._validators = validators;
|
||||
}
|
||||
|
||||
onInit(): void { this.formDirective.addControlGroup(this); }
|
||||
@ -74,4 +80,6 @@ export class NgControlGroup extends ControlContainer implements OnInit,
|
||||
get path(): string[] { return controlPath(this.name, this._parent); }
|
||||
|
||||
get formDirective(): Form { return this._parent.formDirective; }
|
||||
|
||||
get validator(): Function { return Validators.compose(this._validators); }
|
||||
}
|
||||
|
@ -7,13 +7,14 @@ import {
|
||||
import {StringMapWrapper, ListWrapper} from 'angular2/src/core/facade/collection';
|
||||
import {isPresent, isBlank, CONST_EXPR} from 'angular2/src/core/facade/lang';
|
||||
import {Directive} from 'angular2/src/core/metadata';
|
||||
import {forwardRef, Provider} from 'angular2/src/core/di';
|
||||
import {forwardRef, Provider, Optional, Inject} from 'angular2/src/core/di';
|
||||
import {NgControl} from './ng_control';
|
||||
import {Form} from './form_interface';
|
||||
import {NgControlGroup} from './ng_control_group';
|
||||
import {ControlContainer} from './control_container';
|
||||
import {AbstractControl, ControlGroup, Control} from '../model';
|
||||
import {setUpControl} from './shared';
|
||||
import {setUpControl, setUpControlGroup} from './shared';
|
||||
import {Validators, NG_VALIDATORS} from '../validators';
|
||||
|
||||
const formDirectiveProvider =
|
||||
CONST_EXPR(new Provider(ControlContainer, {useExisting: forwardRef(() => NgForm)}));
|
||||
@ -87,9 +88,14 @@ const formDirectiveProvider =
|
||||
exportAs: 'form'
|
||||
})
|
||||
export class NgForm extends ControlContainer implements Form {
|
||||
form: ControlGroup = new ControlGroup({});
|
||||
form: ControlGroup;
|
||||
ngSubmit = new EventEmitter();
|
||||
|
||||
constructor(@Optional() @Inject(NG_VALIDATORS) validators: Function[]) {
|
||||
super();
|
||||
this.form = new ControlGroup({}, null, Validators.compose(validators));
|
||||
}
|
||||
|
||||
get formDirective(): Form { return this; }
|
||||
|
||||
get control(): ControlGroup { return this.form; }
|
||||
@ -124,6 +130,7 @@ export class NgForm extends ControlContainer implements Form {
|
||||
this._later(_ => {
|
||||
var container = this._findContainer(dir.path);
|
||||
var group = new ControlGroup({});
|
||||
setUpControlGroup(group, dir);
|
||||
container.addControl(dir.name, group);
|
||||
group.updateValueAndValidity({emitEvent: false});
|
||||
});
|
||||
|
@ -1,16 +1,18 @@
|
||||
import {CONST_EXPR} from 'angular2/src/core/facade/lang';
|
||||
import {ListWrapper} from 'angular2/src/core/facade/collection';
|
||||
import {ListWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection';
|
||||
import {ObservableWrapper, EventEmitter} from 'angular2/src/core/facade/async';
|
||||
import {SimpleChange} from 'angular2/src/core/change_detection';
|
||||
|
||||
import {OnChanges} from 'angular2/lifecycle_hooks';
|
||||
import {Directive} from 'angular2/src/core/metadata';
|
||||
import {forwardRef, Provider} from 'angular2/src/core/di';
|
||||
import {forwardRef, Provider, Inject, Optional} from 'angular2/src/core/di';
|
||||
import {NgControl} from './ng_control';
|
||||
import {NgControlGroup} from './ng_control_group';
|
||||
import {ControlContainer} from './control_container';
|
||||
import {Form} from './form_interface';
|
||||
import {Control, ControlGroup} from '../model';
|
||||
import {setUpControl} from './shared';
|
||||
import {setUpControl, setUpControlGroup} from './shared';
|
||||
import {Validators, NG_VALIDATORS} from '../validators';
|
||||
|
||||
const formDirectiveProvider =
|
||||
CONST_EXPR(new Provider(ControlContainer, {useExisting: forwardRef(() => NgFormModel)}));
|
||||
@ -100,8 +102,21 @@ export class NgFormModel extends ControlContainer implements Form,
|
||||
form: ControlGroup = null;
|
||||
directives: NgControl[] = [];
|
||||
ngSubmit = new EventEmitter();
|
||||
private _validators: Function[];
|
||||
|
||||
onChanges(_): void { this._updateDomValue(); }
|
||||
constructor(@Optional() @Inject(NG_VALIDATORS) validators: Function[]) {
|
||||
super();
|
||||
this._validators = validators;
|
||||
}
|
||||
|
||||
onChanges(changes: {[key: string]: SimpleChange}): void {
|
||||
if (StringMapWrapper.contains(changes, "form")) {
|
||||
var c = Validators.compose(this._validators);
|
||||
this.form.validator = Validators.compose([this.form.validator, c]);
|
||||
}
|
||||
|
||||
this._updateDomValue();
|
||||
}
|
||||
|
||||
get formDirective(): Form { return this; }
|
||||
|
||||
@ -120,7 +135,11 @@ export class NgFormModel extends ControlContainer implements Form,
|
||||
|
||||
removeControl(dir: NgControl): void { ListWrapper.remove(this.directives, dir); }
|
||||
|
||||
addControlGroup(dir: NgControlGroup) {}
|
||||
addControlGroup(dir: NgControlGroup) {
|
||||
var ctrl: any = this.form.find(dir.path);
|
||||
setUpControlGroup(ctrl, dir);
|
||||
ctrl.updateValueAndValidity({emitEvent: false});
|
||||
}
|
||||
|
||||
removeControlGroup(dir: NgControlGroup) {}
|
||||
|
||||
|
@ -4,7 +4,9 @@ import {BaseException, WrappedException} from 'angular2/src/core/facade/exceptio
|
||||
|
||||
import {ControlContainer} from './control_container';
|
||||
import {NgControl} from './ng_control';
|
||||
import {Control} from '../model';
|
||||
import {AbstractControlDirective} from './abstract_control_directive';
|
||||
import {NgControlGroup} from './ng_control_group';
|
||||
import {Control, ControlGroup} from '../model';
|
||||
import {Validators} from '../validators';
|
||||
import {ControlValueAccessor} from './control_value_accessor';
|
||||
import {ElementRef, QueryList} from 'angular2/src/core/linker';
|
||||
@ -42,7 +44,12 @@ export function setUpControl(control: Control, dir: NgControl): void {
|
||||
dir.valueAccessor.registerOnTouched(() => control.markAsTouched());
|
||||
}
|
||||
|
||||
function _throwError(dir: NgControl, message: string): void {
|
||||
export function setUpControlGroup(control: ControlGroup, dir: NgControlGroup) {
|
||||
if (isBlank(control)) _throwError(dir, "Cannot find control");
|
||||
control.validator = Validators.compose([control.validator, dir.validator]);
|
||||
}
|
||||
|
||||
function _throwError(dir: AbstractControlDirective, message: string): void {
|
||||
var path = dir.path.join(" -> ");
|
||||
throw new BaseException(`${message} '${path}'`);
|
||||
}
|
||||
|
Reference in New Issue
Block a user