refactor: move angular source to /packages rather than modules/@angular

This commit is contained in:
Jason Aden
2017-03-02 10:48:42 -08:00
parent 5ad5301a3e
commit 3e51a19983
1051 changed files with 18 additions and 18 deletions

View File

@ -0,0 +1,120 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Directive, EventEmitter, Inject, Input, OnChanges, Optional, Output, Self, SimpleChanges, forwardRef} from '@angular/core';
import {FormControl} from '../../model';
import {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../../validators';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '../control_value_accessor';
import {NgControl} from '../ng_control';
import {ReactiveErrors} from '../reactive_errors';
import {composeAsyncValidators, composeValidators, isPropertyUpdated, selectValueAccessor, setUpControl} from '../shared';
import {AsyncValidator, AsyncValidatorFn, Validator, ValidatorFn} from '../validators';
export const formControlBinding: any = {
provide: NgControl,
useExisting: forwardRef(() => FormControlDirective)
};
/**
* @whatItDoes Syncs a standalone {@link FormControl} instance to a form control element.
*
* In other words, this directive ensures that any values written to the {@link FormControl}
* instance programmatically will be written to the DOM element (model -> view). Conversely,
* any values written to the DOM element through user input will be reflected in the
* {@link FormControl} instance (view -> model).
*
* @howToUse
*
* Use this directive if you'd like to create and manage a {@link FormControl} instance directly.
* Simply create a {@link FormControl}, save it to your component class, and pass it into the
* {@link FormControlDirective}.
*
* This directive is designed to be used as a standalone control. Unlike {@link FormControlName},
* it does not require that your {@link FormControl} instance be part of any parent
* {@link FormGroup}, and it won't be registered to any {@link FormGroupDirective} that
* exists above it.
*
* **Get the value**: the `value` property is always synced and available on the
* {@link FormControl} instance. See a full list of available properties in
* {@link AbstractControl}.
*
* **Set the value**: You can pass in an initial value when instantiating the {@link FormControl},
* or you can set it programmatically later using {@link AbstractControl.setValue} or
* {@link AbstractControl.patchValue}.
*
* **Listen to value**: If you want to listen to changes in the value of the control, you can
* subscribe to the {@link AbstractControl.valueChanges} event. You can also listen to
* {@link AbstractControl.statusChanges} to be notified when the validation status is
* re-calculated.
*
* ### Example
*
* {@example forms/ts/simpleFormControl/simple_form_control_example.ts region='Component'}
*
* * **npm package**: `@angular/forms`
*
* * **NgModule**: `ReactiveFormsModule`
*
* @stable
*/
@Directive({selector: '[formControl]', providers: [formControlBinding], exportAs: 'ngForm'})
export class FormControlDirective extends NgControl implements OnChanges {
viewModel: any;
@Input('formControl') form: FormControl;
@Input('ngModel') model: any;
@Output('ngModelChange') update = new EventEmitter();
@Input('disabled')
set isDisabled(isDisabled: boolean) { ReactiveErrors.disabledAttrWarning(); }
constructor(@Optional() @Self() @Inject(NG_VALIDATORS) validators: Array<Validator|ValidatorFn>,
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators: Array<AsyncValidator|AsyncValidatorFn>,
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR)
valueAccessors: ControlValueAccessor[]) {
super();
this._rawValidators = validators || [];
this._rawAsyncValidators = asyncValidators || [];
this.valueAccessor = selectValueAccessor(this, valueAccessors);
}
ngOnChanges(changes: SimpleChanges): void {
if (this._isControlChanged(changes)) {
setUpControl(this.form, this);
if (this.control.disabled && this.valueAccessor.setDisabledState) {
this.valueAccessor.setDisabledState(true);
}
this.form.updateValueAndValidity({emitEvent: false});
}
if (isPropertyUpdated(changes, this.viewModel)) {
this.form.setValue(this.model);
this.viewModel = this.model;
}
}
get path(): string[] { return []; }
get validator(): ValidatorFn { return composeValidators(this._rawValidators); }
get asyncValidator(): AsyncValidatorFn {
return composeAsyncValidators(this._rawAsyncValidators);
}
get control(): FormControl { return this.form; }
viewToModelUpdate(newValue: any): void {
this.viewModel = newValue;
this.update.emit(newValue);
}
private _isControlChanged(changes: {[key: string]: any}): boolean {
return changes.hasOwnProperty('form');
}
}

View File

@ -0,0 +1,159 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Directive, EventEmitter, Host, Inject, Input, OnChanges, OnDestroy, Optional, Output, Self, SimpleChanges, SkipSelf, forwardRef} from '@angular/core';
import {FormControl} from '../../model';
import {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../../validators';
import {AbstractFormGroupDirective} from '../abstract_form_group_directive';
import {ControlContainer} from '../control_container';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '../control_value_accessor';
import {NgControl} from '../ng_control';
import {ReactiveErrors} from '../reactive_errors';
import {composeAsyncValidators, composeValidators, controlPath, isPropertyUpdated, selectValueAccessor} from '../shared';
import {AsyncValidator, AsyncValidatorFn, Validator, ValidatorFn} from '../validators';
import {FormGroupDirective} from './form_group_directive';
import {FormArrayName, FormGroupName} from './form_group_name';
export const controlNameBinding: any = {
provide: NgControl,
useExisting: forwardRef(() => FormControlName)
};
/**
* @whatItDoes Syncs a {@link FormControl} in an existing {@link FormGroup} to a form control
* element by name.
*
* In other words, this directive ensures that any values written to the {@link FormControl}
* instance programmatically will be written to the DOM element (model -> view). Conversely,
* any values written to the DOM element through user input will be reflected in the
* {@link FormControl} instance (view -> model).
*
* @howToUse
*
* This directive is designed to be used with a parent {@link FormGroupDirective} (selector:
* `[formGroup]`).
*
* It accepts the string name of the {@link FormControl} instance you want to
* link, and will look for a {@link FormControl} registered with that name in the
* closest {@link FormGroup} or {@link FormArray} above it.
*
* **Access the control**: You can access the {@link FormControl} associated with
* this directive by using the {@link AbstractControl.get} method.
* Ex: `this.form.get('first');`
*
* **Get value**: the `value` property is always synced and available on the {@link FormControl}.
* See a full list of available properties in {@link AbstractControl}.
*
* **Set value**: You can set an initial value for the control when instantiating the
* {@link FormControl}, or you can set it programmatically later using
* {@link AbstractControl.setValue} or {@link AbstractControl.patchValue}.
*
* **Listen to value**: If you want to listen to changes in the value of the control, you can
* subscribe to the {@link AbstractControl.valueChanges} event. You can also listen to
* {@link AbstractControl.statusChanges} to be notified when the validation status is
* re-calculated.
*
* ### Example
*
* In this example, we create form controls for first name and last name.
*
* {@example forms/ts/simpleFormGroup/simple_form_group_example.ts region='Component'}
*
* To see `formControlName` examples with different form control types, see:
*
* * Radio buttons: {@link RadioControlValueAccessor}
* * Selects: {@link SelectControlValueAccessor}
*
* **npm package**: `@angular/forms`
*
* **NgModule**: {@link ReactiveFormsModule}
*
* @stable
*/
@Directive({selector: '[formControlName]', providers: [controlNameBinding]})
export class FormControlName extends NgControl implements OnChanges, OnDestroy {
private _added = false;
/** @internal */
viewModel: any;
/** @internal */
_control: FormControl;
@Input('formControlName') name: string;
// TODO(kara): Replace ngModel with reactive API
@Input('ngModel') model: any;
@Output('ngModelChange') update = new EventEmitter();
@Input('disabled')
set isDisabled(isDisabled: boolean) { ReactiveErrors.disabledAttrWarning(); }
constructor(
@Optional() @Host() @SkipSelf() parent: ControlContainer,
@Optional() @Self() @Inject(NG_VALIDATORS) validators: Array<Validator|ValidatorFn>,
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators:
Array<AsyncValidator|AsyncValidatorFn>,
@Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[]) {
super();
this._parent = parent;
this._rawValidators = validators || [];
this._rawAsyncValidators = asyncValidators || [];
this.valueAccessor = selectValueAccessor(this, valueAccessors);
}
ngOnChanges(changes: SimpleChanges) {
if (!this._added) this._setUpControl();
if (isPropertyUpdated(changes, this.viewModel)) {
this.viewModel = this.model;
this.formDirective.updateModel(this, this.model);
}
}
ngOnDestroy(): void {
if (this.formDirective) {
this.formDirective.removeControl(this);
}
}
viewToModelUpdate(newValue: any): void {
this.viewModel = newValue;
this.update.emit(newValue);
}
get path(): string[] { return controlPath(this.name, this._parent); }
get formDirective(): any { return this._parent ? this._parent.formDirective : null; }
get validator(): ValidatorFn { return composeValidators(this._rawValidators); }
get asyncValidator(): AsyncValidatorFn {
return composeAsyncValidators(this._rawAsyncValidators);
}
get control(): FormControl { return this._control; }
private _checkParentType(): void {
if (!(this._parent instanceof FormGroupName) &&
this._parent instanceof AbstractFormGroupDirective) {
ReactiveErrors.ngModelGroupException();
} else if (
!(this._parent instanceof FormGroupName) && !(this._parent instanceof FormGroupDirective) &&
!(this._parent instanceof FormArrayName)) {
ReactiveErrors.controlParentException();
}
}
private _setUpControl() {
this._checkParentType();
this._control = this.formDirective.addControl(this);
if (this.control.disabled && this.valueAccessor.setDisabledState) {
this.valueAccessor.setDisabledState(true);
}
this._added = true;
}
}

View File

@ -0,0 +1,188 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Directive, EventEmitter, Inject, Input, OnChanges, Optional, Output, Self, SimpleChanges, forwardRef} from '@angular/core';
import {FormArray, FormControl, FormGroup} from '../../model';
import {NG_ASYNC_VALIDATORS, NG_VALIDATORS, Validators} from '../../validators';
import {ControlContainer} from '../control_container';
import {Form} from '../form_interface';
import {ReactiveErrors} from '../reactive_errors';
import {cleanUpControl, composeAsyncValidators, composeValidators, setUpControl, setUpFormContainer} from '../shared';
import {FormControlName} from './form_control_name';
import {FormArrayName, FormGroupName} from './form_group_name';
export const formDirectiveProvider: any = {
provide: ControlContainer,
useExisting: forwardRef(() => FormGroupDirective)
};
/**
* @whatItDoes Binds an existing {@link FormGroup} to a DOM element.
*
* @howToUse
*
* This directive accepts an existing {@link FormGroup} instance. It will then use this
* {@link FormGroup} instance to match any child {@link FormControl}, {@link FormGroup},
* and {@link FormArray} instances to child {@link FormControlName}, {@link FormGroupName},
* and {@link FormArrayName} directives.
*
* **Set value**: You can set the form's initial value when instantiating the
* {@link FormGroup}, or you can set it programmatically later using the {@link FormGroup}'s
* {@link AbstractControl.setValue} or {@link AbstractControl.patchValue} methods.
*
* **Listen to value**: If you want to listen to changes in the value of the form, you can subscribe
* to the {@link FormGroup}'s {@link AbstractControl.valueChanges} event. You can also listen to
* its {@link AbstractControl.statusChanges} event to be notified when the validation status is
* re-calculated.
*
* Furthermore, you can listen to the directive's `ngSubmit` event to be notified when the user has
* triggered a form submission. The `ngSubmit` event will be emitted with the original form
* submission event.
*
* ### Example
*
* In this example, we create form controls for first name and last name.
*
* {@example forms/ts/simpleFormGroup/simple_form_group_example.ts region='Component'}
*
* **npm package**: `@angular/forms`
*
* **NgModule**: {@link ReactiveFormsModule}
*
* @stable
*/
@Directive({
selector: '[formGroup]',
providers: [formDirectiveProvider],
host: {'(submit)': 'onSubmit($event)', '(reset)': 'onReset()'},
exportAs: 'ngForm'
})
export class FormGroupDirective extends ControlContainer implements Form,
OnChanges {
private _submitted: boolean = false;
private _oldForm: FormGroup;
directives: FormControlName[] = [];
@Input('formGroup') form: FormGroup = null;
@Output() ngSubmit = new EventEmitter();
constructor(
@Optional() @Self() @Inject(NG_VALIDATORS) private _validators: any[],
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private _asyncValidators: any[]) {
super();
}
ngOnChanges(changes: SimpleChanges): void {
this._checkFormPresent();
if (changes.hasOwnProperty('form')) {
this._updateValidators();
this._updateDomValue();
this._updateRegistrations();
}
}
get submitted(): boolean { return this._submitted; }
get formDirective(): Form { return this; }
get control(): FormGroup { return this.form; }
get path(): string[] { return []; }
addControl(dir: FormControlName): FormControl {
const ctrl: any = this.form.get(dir.path);
setUpControl(ctrl, dir);
ctrl.updateValueAndValidity({emitEvent: false});
this.directives.push(dir);
return ctrl;
}
getControl(dir: FormControlName): FormControl { return <FormControl>this.form.get(dir.path); }
removeControl(dir: FormControlName): void { remove(this.directives, dir); }
addFormGroup(dir: FormGroupName): void {
const ctrl: any = this.form.get(dir.path);
setUpFormContainer(ctrl, dir);
ctrl.updateValueAndValidity({emitEvent: false});
}
removeFormGroup(dir: FormGroupName): void {}
getFormGroup(dir: FormGroupName): FormGroup { return <FormGroup>this.form.get(dir.path); }
addFormArray(dir: FormArrayName): void {
const ctrl: any = this.form.get(dir.path);
setUpFormContainer(ctrl, dir);
ctrl.updateValueAndValidity({emitEvent: false});
}
removeFormArray(dir: FormArrayName): void {}
getFormArray(dir: FormArrayName): FormArray { return <FormArray>this.form.get(dir.path); }
updateModel(dir: FormControlName, value: any): void {
const ctrl  = <FormControl>this.form.get(dir.path);
ctrl.setValue(value);
}
onSubmit($event: Event): boolean {
this._submitted = true;
this.ngSubmit.emit($event);
return false;
}
onReset(): void { this.resetForm(); }
resetForm(value: any = undefined): void {
this.form.reset(value);
this._submitted = false;
}
/** @internal */
_updateDomValue() {
this.directives.forEach(dir => {
const newCtrl: any = this.form.get(dir.path);
if (dir._control !== newCtrl) {
cleanUpControl(dir._control, dir);
if (newCtrl) setUpControl(newCtrl, dir);
dir._control = newCtrl;
}
});
this.form._updateTreeValidity({emitEvent: false});
}
private _updateRegistrations() {
this.form._registerOnCollectionChange(() => this._updateDomValue());
if (this._oldForm) this._oldForm._registerOnCollectionChange(() => {});
this._oldForm = this.form;
}
private _updateValidators() {
const sync = composeValidators(this._validators);
this.form.validator = Validators.compose([this.form.validator, sync]);
const async = composeAsyncValidators(this._asyncValidators);
this.form.asyncValidator = Validators.composeAsync([this.form.asyncValidator, async]);
}
private _checkFormPresent() {
if (!this.form) {
ReactiveErrors.missingFormException();
}
}
}
function remove<T>(list: T[], el: T): void {
const index = list.indexOf(el);
if (index > -1) {
list.splice(index, 1);
}
}

View File

@ -0,0 +1,200 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Directive, Host, Inject, Input, OnDestroy, OnInit, Optional, Self, SkipSelf, forwardRef} from '@angular/core';
import {FormArray} from '../../model';
import {NG_ASYNC_VALIDATORS, NG_VALIDATORS} from '../../validators';
import {AbstractFormGroupDirective} from '../abstract_form_group_directive';
import {ControlContainer} from '../control_container';
import {ReactiveErrors} from '../reactive_errors';
import {composeAsyncValidators, composeValidators, controlPath} from '../shared';
import {AsyncValidatorFn, ValidatorFn} from '../validators';
import {FormGroupDirective} from './form_group_directive';
export const formGroupNameProvider: any = {
provide: ControlContainer,
useExisting: forwardRef(() => FormGroupName)
};
/**
* @whatItDoes Syncs a nested {@link FormGroup} to a DOM element.
*
* @howToUse
*
* This directive can only be used with a parent {@link FormGroupDirective} (selector:
* `[formGroup]`).
*
* It accepts the string name of the nested {@link FormGroup} you want to link, and
* will look for a {@link FormGroup} registered with that name in the parent
* {@link FormGroup} instance you passed into {@link FormGroupDirective}.
*
* Nested form groups can come in handy when you want to validate a sub-group of a
* form separately from the rest or when you'd like to group the values of certain
* controls into their own nested object.
*
* **Access the group**: You can access the associated {@link FormGroup} using the
* {@link AbstractControl.get} method. Ex: `this.form.get('name')`.
*
* You can also access individual controls within the group using dot syntax.
* Ex: `this.form.get('name.first')`
*
* **Get the value**: the `value` property is always synced and available on the
* {@link FormGroup}. See a full list of available properties in {@link AbstractControl}.
*
* **Set the value**: You can set an initial value for each child control when instantiating
* the {@link FormGroup}, or you can set it programmatically later using
* {@link AbstractControl.setValue} or {@link AbstractControl.patchValue}.
*
* **Listen to value**: If you want to listen to changes in the value of the group, you can
* subscribe to the {@link AbstractControl.valueChanges} event. You can also listen to
* {@link AbstractControl.statusChanges} to be notified when the validation status is
* re-calculated.
*
* ### Example
*
* {@example forms/ts/nestedFormGroup/nested_form_group_example.ts region='Component'}
*
* * **npm package**: `@angular/forms`
*
* * **NgModule**: `ReactiveFormsModule`
*
* @stable
*/
@Directive({selector: '[formGroupName]', providers: [formGroupNameProvider]})
export class FormGroupName extends AbstractFormGroupDirective implements OnInit, OnDestroy {
@Input('formGroupName') name: string;
constructor(
@Optional() @Host() @SkipSelf() parent: ControlContainer,
@Optional() @Self() @Inject(NG_VALIDATORS) validators: any[],
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators: any[]) {
super();
this._parent = parent;
this._validators = validators;
this._asyncValidators = asyncValidators;
}
/** @internal */
_checkParentType(): void {
if (_hasInvalidParent(this._parent)) {
ReactiveErrors.groupParentException();
}
}
}
export const formArrayNameProvider: any = {
provide: ControlContainer,
useExisting: forwardRef(() => FormArrayName)
};
/**
* @whatItDoes Syncs a nested {@link FormArray} to a DOM element.
*
* @howToUse
*
* This directive is designed to be used with a parent {@link FormGroupDirective} (selector:
* `[formGroup]`).
*
* It accepts the string name of the nested {@link FormArray} you want to link, and
* will look for a {@link FormArray} registered with that name in the parent
* {@link FormGroup} instance you passed into {@link FormGroupDirective}.
*
* Nested form arrays can come in handy when you have a group of form controls but
* you're not sure how many there will be. Form arrays allow you to create new
* form controls dynamically.
*
* **Access the array**: You can access the associated {@link FormArray} using the
* {@link AbstractControl.get} method on the parent {@link FormGroup}.
* Ex: `this.form.get('cities')`.
*
* **Get the value**: the `value` property is always synced and available on the
* {@link FormArray}. See a full list of available properties in {@link AbstractControl}.
*
* **Set the value**: You can set an initial value for each child control when instantiating
* the {@link FormArray}, or you can set the value programmatically later using the
* {@link FormArray}'s {@link AbstractControl.setValue} or {@link AbstractControl.patchValue}
* methods.
*
* **Listen to value**: If you want to listen to changes in the value of the array, you can
* subscribe to the {@link FormArray}'s {@link AbstractControl.valueChanges} event. You can also
* listen to its {@link AbstractControl.statusChanges} event to be notified when the validation
* status is re-calculated.
*
* **Add new controls**: You can add new controls to the {@link FormArray} dynamically by
* calling its {@link FormArray.push} method.
* Ex: `this.form.get('cities').push(new FormControl());`
*
* ### Example
*
* {@example forms/ts/nestedFormArray/nested_form_array_example.ts region='Component'}
*
* * **npm package**: `@angular/forms`
*
* * **NgModule**: `ReactiveFormsModule`
*
* @stable
*/
@Directive({selector: '[formArrayName]', providers: [formArrayNameProvider]})
export class FormArrayName extends ControlContainer implements OnInit, OnDestroy {
/** @internal */
_parent: ControlContainer;
/** @internal */
_validators: any[];
/** @internal */
_asyncValidators: any[];
@Input('formArrayName') name: string;
constructor(
@Optional() @Host() @SkipSelf() parent: ControlContainer,
@Optional() @Self() @Inject(NG_VALIDATORS) validators: any[],
@Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators: any[]) {
super();
this._parent = parent;
this._validators = validators;
this._asyncValidators = asyncValidators;
}
ngOnInit(): void {
this._checkParentType();
this.formDirective.addFormArray(this);
}
ngOnDestroy(): void {
if (this.formDirective) {
this.formDirective.removeFormArray(this);
}
}
get control(): FormArray { return this.formDirective.getFormArray(this); }
get formDirective(): FormGroupDirective {
return this._parent ? <FormGroupDirective>this._parent.formDirective : null;
}
get path(): string[] { return controlPath(this.name, this._parent); }
get validator(): ValidatorFn { return composeValidators(this._validators); }
get asyncValidator(): AsyncValidatorFn { return composeAsyncValidators(this._asyncValidators); }
private _checkParentType(): void {
if (_hasInvalidParent(this._parent)) {
ReactiveErrors.arrayParentException();
}
}
}
function _hasInvalidParent(parent: ControlContainer): boolean {
return !(parent instanceof FormGroupName) && !(parent instanceof FormGroupDirective) &&
!(parent instanceof FormArrayName);
}