| 
									
										
										
										
											2016-06-23 09:47:54 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @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
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-10 10:09:50 -07:00
										 |  |  | import {NgFor, NgIf} from '@angular/common'; | 
					
						
							| 
									
										
										
										
											2016-07-21 17:12:00 -07:00
										 |  |  | import {Component, Directive, EventEmitter, Input, Output, forwardRef} from '@angular/core'; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | import {ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/testing'; | 
					
						
							|  |  |  | import {ControlValueAccessor, FormArray, FormControl, FormGroup, FormGroupDirective, FormsModule, NG_ASYNC_VALIDATORS, NG_VALIDATORS, NgControl, ReactiveFormsModule, Validator, Validators} from '@angular/forms'; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | import {By} from '@angular/platform-browser/src/dom/debug/by'; | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; | 
					
						
							| 
									
										
										
										
											2016-06-23 16:42:25 -07:00
										 |  |  | import {dispatchEvent} from '@angular/platform-browser/testing/browser_util'; | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-14 18:23:40 -07:00
										 |  |  | import {ListWrapper} from '../src/facade/collection'; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | import {AbstractControl} from '../src/model'; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | export function main() { | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  |   describe('reactive forms integration tests', () => { | 
					
						
							| 
									
										
											  
											
												feat(forms): add modules for forms and deprecatedForms (#9859)
Closes #9732
BREAKING CHANGE:
We have removed the deprecated form directives from the built-in platform directive list, so apps are not required to package forms with their app. This also makes forms friendly to offline compilation.
Instead, we have exposed three modules:
OLD API:
- `DeprecatedFormsModule`
NEW API:
- `FormsModule`
- `ReactiveFormsModule`
If you provide one of these modules, the default forms directives and providers from that module will be available to you app-wide.  Note: You can provide both the `FormsModule` and the `ReactiveFormsModule` together if you like, but they are fully-functional separately.
**Before:**
```ts
import {disableDeprecatedForms, provideForms} from @angular/forms;
bootstrap(App, [
   disableDeprecatedForms(),
   provideForms()
]);
```
**After:**
```ts
import {DeprecatedFormsModule} from @angular/common;
bootstrap(App, {modules: [DeprecatedFormsModule] });
```
-OR-
```ts
import {FormsModule} from @angular/forms;
bootstrap(App, {modules: [FormsModule] });
```
-OR-
```ts
import {ReactiveFormsModule} from @angular/forms;
bootstrap(App, {modules: [ReactiveFormsModule] });
```
You can also choose not to provide any forms module and run your app without forms.
Or you can choose not to provide any forms module *and* provide form directives at will.  This will allow you to use the deprecatedForms API for some components and not others.
```
import {FORM_DIRECTIVES, FORM_PROVIDERS} from @angular/forms;
@Component({
   selector: some-comp,
   directives: [FORM_DIRECTIVES],
   providers: [FORM_PROVIDERS]
})
class SomeComp
```
											
										 
											2016-07-07 11:32:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-28 04:54:49 -07:00
										 |  |  |     beforeEach(() => { | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       TestBed.configureTestingModule({ | 
					
						
							|  |  |  |         imports: [FormsModule, ReactiveFormsModule], | 
					
						
							|  |  |  |         declarations: [ | 
					
						
							|  |  |  |           FormControlComp, FormGroupComp, FormArrayComp, FormArrayNestedGroup, | 
					
						
							|  |  |  |           FormControlNameSelect, FormControlNumberInput, FormControlRadioButtons, WrappedValue, | 
					
						
							|  |  |  |           WrappedValueForm, MyInput, MyInputForm, FormGroupNgModel, FormControlNgModel, | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |           LoginIsEmptyValidator, LoginIsEmptyWrapper, ValidationBindingsForm, UniqLoginValidator, | 
					
						
							|  |  |  |           UniqLoginWrapper, NestedFormGroupComp | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         ] | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-07-28 04:54:49 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |     describe('basic functionality', () => { | 
					
						
							|  |  |  |       it('should work with single controls', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormControlComp); | 
					
						
							|  |  |  |         const control = new FormControl('old value'); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.control = control; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         // model -> view
 | 
					
						
							|  |  |  |         const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         expect(input.nativeElement.value).toEqual('old value'); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         input.nativeElement.value = 'updated value'; | 
					
						
							|  |  |  |         dispatchEvent(input.nativeElement, 'input'); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         // view -> model
 | 
					
						
							|  |  |  |         expect(control.value).toEqual('updated value'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should work with formGroups (model -> view)', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = | 
					
						
							|  |  |  |             new FormGroup({'login': new FormControl('loginValue')}); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         expect(input.nativeElement.value).toEqual('loginValue'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('work with formGroups (view -> model)', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         const form = new FormGroup({'login': new FormControl('oldValue')}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         input.nativeElement.value = 'updatedValue'; | 
					
						
							|  |  |  |         dispatchEvent(input.nativeElement, 'input'); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         expect(form.value).toEqual({'login': 'updatedValue'}); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('rebound form groups', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should update DOM elements initially', () => { | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = | 
					
						
							|  |  |  |             new FormGroup({'login': new FormControl('oldValue')}); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         fixture.debugElement.componentInstance.form = | 
					
						
							|  |  |  |             new FormGroup({'login': new FormControl('newValue')}); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-08-02 15:53:34 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         expect(input.nativeElement.value).toEqual('newValue'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it('should update model when UI changes', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = | 
					
						
							|  |  |  |             new FormGroup({'login': new FormControl('oldValue')}); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const newForm = new FormGroup({'login': new FormControl('newValue')}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = newForm; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         input.nativeElement.value = 'Nancy'; | 
					
						
							|  |  |  |         dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(newForm.value).toEqual({login: 'Nancy'}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         newForm.setValue({login: 'Carson'}); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  |         expect(input.nativeElement.value).toEqual('Carson'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should work with radio buttons when reusing control', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormControlRadioButtons); | 
					
						
							|  |  |  |         const food = new FormControl('chicken'); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = | 
					
						
							|  |  |  |             new FormGroup({'food': food, 'drink': new FormControl('')}); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const newForm = new FormGroup({'food': food, 'drink': new FormControl('')}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = newForm; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         newForm.setValue({food: 'fish', drink: ''}); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  |         const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |         expect(inputs[0].nativeElement.checked).toBe(false); | 
					
						
							|  |  |  |         expect(inputs[1].nativeElement.checked).toBe(true); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should update nested form group model when UI changes', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(NestedFormGroupComp); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = new FormGroup( | 
					
						
							|  |  |  |             {'signin': new FormGroup({'login': new FormControl(), 'password': new FormControl()})}); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const newForm = new FormGroup({ | 
					
						
							|  |  |  |           'signin': new FormGroup( | 
					
						
							|  |  |  |               {'login': new FormControl('Nancy'), 'password': new FormControl('secret')}) | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = newForm; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |         expect(inputs[0].nativeElement.value).toEqual('Nancy'); | 
					
						
							|  |  |  |         expect(inputs[1].nativeElement.value).toEqual('secret'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         inputs[0].nativeElement.value = 'Carson'; | 
					
						
							|  |  |  |         dispatchEvent(inputs[0].nativeElement, 'input'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(newForm.value).toEqual({signin: {login: 'Carson', password: 'secret'}}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         newForm.setValue({signin: {login: 'Bess', password: 'otherpass'}}); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  |         expect(inputs[0].nativeElement.value).toEqual('Bess'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |       it('should pick up dir validators from form controls', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(LoginIsEmptyWrapper); | 
					
						
							|  |  |  |         const form = new FormGroup({ | 
					
						
							|  |  |  |           'login': new FormControl(''), | 
					
						
							|  |  |  |           'min': new FormControl(''), | 
					
						
							|  |  |  |           'max': new FormControl(''), | 
					
						
							|  |  |  |           'pattern': new FormControl('') | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  |         expect(form.get('login').errors).toEqual({required: true}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const newForm = new FormGroup({ | 
					
						
							|  |  |  |           'login': new FormControl(''), | 
					
						
							|  |  |  |           'min': new FormControl(''), | 
					
						
							|  |  |  |           'max': new FormControl(''), | 
					
						
							|  |  |  |           'pattern': new FormControl('') | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = newForm; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(newForm.get('login').errors).toEqual({required: true}); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |       it('should pick up dir validators from nested form groups', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(NestedFormGroupComp); | 
					
						
							|  |  |  |         const form = new FormGroup({ | 
					
						
							|  |  |  |           'signin': | 
					
						
							|  |  |  |               new FormGroup({'login': new FormControl(''), 'password': new FormControl('')}) | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  |         expect(form.get('signin').valid).toBe(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const newForm = new FormGroup({ | 
					
						
							|  |  |  |           'signin': | 
					
						
							|  |  |  |               new FormGroup({'login': new FormControl(''), 'password': new FormControl('')}) | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = newForm; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(form.get('signin').valid).toBe(false); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should strip named controls that are not found', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(NestedFormGroupComp); | 
					
						
							|  |  |  |         const form = new FormGroup({ | 
					
						
							|  |  |  |           'signin': | 
					
						
							|  |  |  |               new FormGroup({'login': new FormControl(''), 'password': new FormControl('')}) | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         form.addControl('email', new FormControl('email')); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let emailInput = fixture.debugElement.query(By.css('[formControlName="email"]')); | 
					
						
							|  |  |  |         expect(emailInput.nativeElement.value).toEqual('email'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const newForm = new FormGroup({ | 
					
						
							|  |  |  |           'signin': | 
					
						
							|  |  |  |               new FormGroup({'login': new FormControl(''), 'password': new FormControl('')}) | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = newForm; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         emailInput = fixture.debugElement.query(By.css('[formControlName="email"]')); | 
					
						
							|  |  |  |         expect(emailInput).toBe(null); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should strip array controls that are not found', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormArrayComp); | 
					
						
							|  |  |  |         const cityArray = new FormArray([new FormControl('SF'), new FormControl('NY')]); | 
					
						
							|  |  |  |         const form = new FormGroup({cities: cityArray}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.cityArray = cityArray; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |         expect(inputs[2]).not.toBeDefined(); | 
					
						
							|  |  |  |         cityArray.push(new FormControl('LA')); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |         expect(inputs[2]).toBeDefined(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const newArr = new FormArray([new FormControl('SF'), new FormControl('NY')]); | 
					
						
							|  |  |  |         const newForm = new FormGroup({cities: newArr}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = newForm; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.cityArray = newArr; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |         expect(inputs[2]).not.toBeDefined(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |     describe('form arrays', () => { | 
					
						
							|  |  |  |       it('should support form arrays', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormArrayComp); | 
					
						
							|  |  |  |         const cityArray = new FormArray([new FormControl('SF'), new FormControl('NY')]); | 
					
						
							|  |  |  |         const form = new FormGroup({cities: cityArray}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.cityArray = cityArray; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         // model -> view
 | 
					
						
							|  |  |  |         expect(inputs[0].nativeElement.value).toEqual('SF'); | 
					
						
							|  |  |  |         expect(inputs[1].nativeElement.value).toEqual('NY'); | 
					
						
							|  |  |  |         expect(form.value).toEqual({cities: ['SF', 'NY']}); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         inputs[0].nativeElement.value = 'LA'; | 
					
						
							|  |  |  |         dispatchEvent(inputs[0].nativeElement, 'input'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         //  view -> model
 | 
					
						
							|  |  |  |         expect(form.value).toEqual({cities: ['LA', 'NY']}); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should support pushing new controls to form arrays', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormArrayComp); | 
					
						
							|  |  |  |         const cityArray = new FormArray([new FormControl('SF'), new FormControl('NY')]); | 
					
						
							|  |  |  |         const form = new FormGroup({cities: cityArray}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.cityArray = cityArray; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         cityArray.push(new FormControl('LA')); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |         expect(inputs[2].nativeElement.value).toEqual('LA'); | 
					
						
							|  |  |  |         expect(form.value).toEqual({cities: ['SF', 'NY', 'LA']}); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should support form groups nested in form arrays', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormArrayNestedGroup); | 
					
						
							|  |  |  |         const cityArray = new FormArray([ | 
					
						
							|  |  |  |           new FormGroup({town: new FormControl('SF'), state: new FormControl('CA')}), | 
					
						
							|  |  |  |           new FormGroup({town: new FormControl('NY'), state: new FormControl('NY')}) | 
					
						
							|  |  |  |         ]); | 
					
						
							|  |  |  |         const form = new FormGroup({cities: cityArray}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.cityArray = cityArray; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |         expect(inputs[0].nativeElement.value).toEqual('SF'); | 
					
						
							|  |  |  |         expect(inputs[1].nativeElement.value).toEqual('CA'); | 
					
						
							|  |  |  |         expect(inputs[2].nativeElement.value).toEqual('NY'); | 
					
						
							|  |  |  |         expect(inputs[3].nativeElement.value).toEqual('NY'); | 
					
						
							|  |  |  |         expect(form.value).toEqual({ | 
					
						
							|  |  |  |           cities: [{town: 'SF', state: 'CA'}, {town: 'NY', state: 'NY'}] | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         inputs[0].nativeElement.value = 'LA'; | 
					
						
							|  |  |  |         dispatchEvent(inputs[0].nativeElement, 'input'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(form.value).toEqual({ | 
					
						
							|  |  |  |           cities: [{town: 'LA', state: 'CA'}, {town: 'NY', state: 'NY'}] | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |     describe('programmatic changes', () => { | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |       it('should update the value in the DOM when setValue() is called', () => { | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         const login = new FormControl('oldValue'); | 
					
						
							|  |  |  |         const form = new FormGroup({'login': login}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         login.setValue('newValue'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         expect(input.nativeElement.value).toEqual('newValue'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |       describe('disabled controls', () => { | 
					
						
							|  |  |  |         it('should add disabled attribute to an individual control when instantiated as disabled', | 
					
						
							|  |  |  |            () => { | 
					
						
							|  |  |  |              const fixture = TestBed.createComponent(FormControlComp); | 
					
						
							|  |  |  |              const control = new FormControl({value: 'some value', disabled: true}); | 
					
						
							|  |  |  |              fixture.debugElement.componentInstance.control = control; | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |              expect(input.nativeElement.disabled).toBe(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              control.enable(); | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							|  |  |  |              expect(input.nativeElement.disabled).toBe(false); | 
					
						
							|  |  |  |            }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should add disabled attribute to formControlName when instantiated as disabled', () => { | 
					
						
							|  |  |  |           const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |           const control = new FormControl({value: 'some value', disabled: true}); | 
					
						
							|  |  |  |           fixture.debugElement.componentInstance.form = new FormGroup({login: control}); | 
					
						
							|  |  |  |           fixture.debugElement.componentInstance.control = control; | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |           expect(input.nativeElement.disabled).toBe(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           control.enable(); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  |           expect(input.nativeElement.disabled).toBe(false); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should add disabled attribute to an individual control when disable() is called', | 
					
						
							|  |  |  |            () => { | 
					
						
							|  |  |  |              const fixture = TestBed.createComponent(FormControlComp); | 
					
						
							|  |  |  |              const control = new FormControl('some value'); | 
					
						
							|  |  |  |              fixture.debugElement.componentInstance.control = control; | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              control.disable(); | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |              expect(input.nativeElement.disabled).toBe(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              control.enable(); | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							|  |  |  |              expect(input.nativeElement.disabled).toBe(false); | 
					
						
							|  |  |  |            }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should add disabled attribute to child controls when disable() is called on group', | 
					
						
							|  |  |  |            () => { | 
					
						
							|  |  |  |              const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |              const form = new FormGroup({'login': new FormControl('login')}); | 
					
						
							|  |  |  |              fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              form.disable(); | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |              expect(inputs[0].nativeElement.disabled).toBe(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              form.enable(); | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							|  |  |  |              expect(inputs[0].nativeElement.disabled).toBe(false); | 
					
						
							|  |  |  |            }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should not add disabled attribute to custom controls when disable() is called', () => { | 
					
						
							|  |  |  |           const fixture = TestBed.createComponent(MyInputForm); | 
					
						
							|  |  |  |           const control = new FormControl('some value'); | 
					
						
							|  |  |  |           fixture.debugElement.componentInstance.form = new FormGroup({login: control}); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           control.disable(); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const input = fixture.debugElement.query(By.css('my-input')); | 
					
						
							|  |  |  |           expect(input.nativeElement.getAttribute('disabled')).toBe(null); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |     describe('user input', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should mark controls as touched after interacting with the DOM control', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         const login = new FormControl('oldValue'); | 
					
						
							|  |  |  |         const form = new FormGroup({'login': login}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const loginEl = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         expect(login.touched).toBe(false); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         dispatchEvent(loginEl.nativeElement, 'blur'); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         expect(login.touched).toBe(true); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |     describe('submit and reset events', () => { | 
					
						
							|  |  |  |       it('should emit ngSubmit event on submit', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = | 
					
						
							|  |  |  |             new FormGroup({'login': new FormControl('loginValue')}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.data = 'should be changed'; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const formEl = fixture.debugElement.query(By.css('form')).nativeElement; | 
					
						
							|  |  |  |         dispatchEvent(formEl, 'submit'); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  |         expect(fixture.debugElement.componentInstance.data).toEqual('submitted'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should mark formGroup as submitted on submit event', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = | 
					
						
							|  |  |  |             new FormGroup({'login': new FormControl('loginValue')}); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const formGroupDir = fixture.debugElement.children[0].injector.get(FormGroupDirective); | 
					
						
							|  |  |  |         expect(formGroupDir.submitted).toBe(false); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const formEl = fixture.debugElement.query(By.css('form')).nativeElement; | 
					
						
							|  |  |  |         dispatchEvent(formEl, 'submit'); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  |         expect(formGroupDir.submitted).toEqual(true); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should set value in UI when form resets to that value programmatically', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         const login = new FormControl('some value'); | 
					
						
							|  |  |  |         const form = new FormGroup({'login': login}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const loginEl = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							|  |  |  |         expect(loginEl.value).toBe('some value'); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         form.reset({'login': 'reset value'}); | 
					
						
							|  |  |  |         expect(loginEl.value).toBe('reset value'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should clear value in UI when form resets programmatically', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         const login = new FormControl('some value'); | 
					
						
							|  |  |  |         const form = new FormGroup({'login': login}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const loginEl = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							|  |  |  |         expect(loginEl.value).toBe('some value'); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         form.reset(); | 
					
						
							|  |  |  |         expect(loginEl.value).toBe(''); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |     describe('value changes and status changes', () => { | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should mark controls as dirty before emitting a value change event', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         const login = new FormControl('oldValue'); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = new FormGroup({'login': login}); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         login.valueChanges.subscribe(() => { expect(login.dirty).toBe(true); }); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const loginEl = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							|  |  |  |         loginEl.value = 'newValue'; | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         dispatchEvent(loginEl, 'input'); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should mark control as pristine before emitting a value change event when resetting ', | 
					
						
							|  |  |  |          () => { | 
					
						
							|  |  |  |            const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |            const login = new FormControl('oldValue'); | 
					
						
							|  |  |  |            const form = new FormGroup({'login': login}); | 
					
						
							|  |  |  |            fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            const loginEl = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							|  |  |  |            loginEl.value = 'newValue'; | 
					
						
							|  |  |  |            dispatchEvent(loginEl, 'input'); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            expect(login.pristine).toBe(false); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            login.valueChanges.subscribe(() => { expect(login.pristine).toBe(true); }); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            form.reset(); | 
					
						
							|  |  |  |          }); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |     describe('setting status classes', () => { | 
					
						
							|  |  |  |       it('should work with single fields', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormControlComp); | 
					
						
							|  |  |  |         const control = new FormControl('', Validators.required); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.control = control; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const input = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							|  |  |  |         expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         dispatchEvent(input, 'blur'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         input.value = 'updatedValue'; | 
					
						
							|  |  |  |         dispatchEvent(input, 'input'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should work with single fields in parent forms', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         const form = new FormGroup({'login': new FormControl('', Validators.required)}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-07-12 15:02:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const input = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							|  |  |  |         expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         dispatchEvent(input, 'blur'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         input.value = 'updatedValue'; | 
					
						
							|  |  |  |         dispatchEvent(input, 'input'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should work with formGroup', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         const form = new FormGroup({'login': new FormControl('', Validators.required)}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const input = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							|  |  |  |         const formEl = fixture.debugElement.query(By.css('form')).nativeElement; | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         expect(sortedClassList(formEl)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dispatchEvent(input, 'blur'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(sortedClassList(formEl)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         input.value = 'updatedValue'; | 
					
						
							|  |  |  |         dispatchEvent(input, 'input'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(sortedClassList(formEl)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('value accessors', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should support <input> without type', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent( | 
					
						
							|  |  |  |             FormControlComp, {set: {template: `<input [formControl]="control">`}}); | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormControlComp); | 
					
						
							|  |  |  |         const control = new FormControl('old'); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.control = control; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // model -> view
 | 
					
						
							|  |  |  |         const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         expect(input.nativeElement.value).toEqual('old'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         input.nativeElement.value = 'new'; | 
					
						
							|  |  |  |         dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // view -> model
 | 
					
						
							|  |  |  |         expect(control.value).toEqual('new'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should support <input type=text>', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         const form = new FormGroup({'login': new FormControl('old')}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // model -> view
 | 
					
						
							|  |  |  |         const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         expect(input.nativeElement.value).toEqual('old'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         input.nativeElement.value = 'new'; | 
					
						
							|  |  |  |         dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // view -> model
 | 
					
						
							|  |  |  |         expect(form.value).toEqual({'login': 'new'}); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should ignore the change event for <input type=text>', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         const form = new FormGroup({'login': new FormControl('oldValue')}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         form.valueChanges.subscribe({next: (value) => { throw 'Should not happen'; }}); | 
					
						
							|  |  |  |         input.nativeElement.value = 'updatedValue'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dispatchEvent(input.nativeElement, 'change'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should support <textarea>', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent( | 
					
						
							|  |  |  |             FormControlComp, {set: {template: `<textarea [formControl]="control"></textarea>`}}); | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormControlComp); | 
					
						
							|  |  |  |         const control = new FormControl('old'); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.control = control; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // model -> view
 | 
					
						
							|  |  |  |         const textarea = fixture.debugElement.query(By.css('textarea')); | 
					
						
							|  |  |  |         expect(textarea.nativeElement.value).toEqual('old'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         textarea.nativeElement.value = 'new'; | 
					
						
							|  |  |  |         dispatchEvent(textarea.nativeElement, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // view -> model
 | 
					
						
							|  |  |  |         expect(control.value).toEqual('new'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should support <type=checkbox>', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent( | 
					
						
							|  |  |  |             FormControlComp, {set: {template: `<input type="checkbox" [formControl]="control">`}}); | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormControlComp); | 
					
						
							|  |  |  |         const control = new FormControl(true); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.control = control; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // model -> view
 | 
					
						
							|  |  |  |         const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         expect(input.nativeElement.checked).toBe(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         input.nativeElement.checked = false; | 
					
						
							|  |  |  |         dispatchEvent(input.nativeElement, 'change'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // view -> model
 | 
					
						
							|  |  |  |         expect(control.value).toBe(false); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should support <select>', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormControlNameSelect); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // model -> view
 | 
					
						
							|  |  |  |         const select = fixture.debugElement.query(By.css('select')); | 
					
						
							|  |  |  |         const sfOption = fixture.debugElement.query(By.css('option')); | 
					
						
							|  |  |  |         expect(select.nativeElement.value).toEqual('SF'); | 
					
						
							|  |  |  |         expect(sfOption.nativeElement.selected).toBe(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         select.nativeElement.value = 'NY'; | 
					
						
							|  |  |  |         dispatchEvent(select.nativeElement, 'change'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // view -> model
 | 
					
						
							|  |  |  |         expect(sfOption.nativeElement.selected).toBe(false); | 
					
						
							|  |  |  |         expect(fixture.debugElement.componentInstance.form.value).toEqual({'city': 'NY'}); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('should support <type=number>', () => { | 
					
						
							|  |  |  |         it('with basic use case', () => { | 
					
						
							|  |  |  |           const fixture = TestBed.createComponent(FormControlNumberInput); | 
					
						
							|  |  |  |           const control = new FormControl(10); | 
					
						
							|  |  |  |           fixture.debugElement.componentInstance.control = control; | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // model -> view
 | 
					
						
							|  |  |  |           const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |           expect(input.nativeElement.value).toEqual('10'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           input.nativeElement.value = '20'; | 
					
						
							|  |  |  |           dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // view -> model
 | 
					
						
							|  |  |  |           expect(control.value).toEqual(20); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('when value is cleared in the UI', () => { | 
					
						
							|  |  |  |           const fixture = TestBed.createComponent(FormControlNumberInput); | 
					
						
							|  |  |  |           const control = new FormControl(10, Validators.required); | 
					
						
							|  |  |  |           fixture.debugElement.componentInstance.control = control; | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |           input.nativeElement.value = ''; | 
					
						
							|  |  |  |           dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(control.valid).toBe(false); | 
					
						
							|  |  |  |           expect(control.value).toEqual(null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           input.nativeElement.value = '0'; | 
					
						
							|  |  |  |           dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(control.valid).toBe(true); | 
					
						
							|  |  |  |           expect(control.value).toEqual(0); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('when value is cleared programmatically', () => { | 
					
						
							|  |  |  |           const fixture = TestBed.createComponent(FormControlNumberInput); | 
					
						
							|  |  |  |           const control = new FormControl(10); | 
					
						
							|  |  |  |           fixture.debugElement.componentInstance.control = control; | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           control.setValue(null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |           expect(input.nativeElement.value).toEqual(''); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('should support <type=radio>', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should support <type=radio>', () => { | 
					
						
							|  |  |  |           const fixture = TestBed.createComponent(FormControlRadioButtons); | 
					
						
							|  |  |  |           const form = | 
					
						
							|  |  |  |               new FormGroup({'food': new FormControl('fish'), 'drink': new FormControl('sprite')}); | 
					
						
							|  |  |  |           fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // model -> view
 | 
					
						
							|  |  |  |           const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |           expect(inputs[0].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |           expect(inputs[1].nativeElement.checked).toEqual(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           dispatchEvent(inputs[0].nativeElement, 'change'); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // view -> model
 | 
					
						
							|  |  |  |           expect(form.get('food').value).toEqual('chicken'); | 
					
						
							|  |  |  |           expect(inputs[1].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           form.get('food').setValue('fish'); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // programmatic change -> view
 | 
					
						
							|  |  |  |           expect(inputs[0].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |           expect(inputs[1].nativeElement.checked).toEqual(true); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should use formControlName to group radio buttons when name is absent', () => { | 
					
						
							|  |  |  |           const fixture = TestBed.createComponent(FormControlRadioButtons); | 
					
						
							|  |  |  |           const foodCtrl = new FormControl('fish'); | 
					
						
							|  |  |  |           const drinkCtrl = new FormControl('sprite'); | 
					
						
							|  |  |  |           fixture.debugElement.componentInstance.form = | 
					
						
							|  |  |  |               new FormGroup({'food': foodCtrl, 'drink': drinkCtrl}); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |           expect(inputs[0].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |           expect(inputs[1].nativeElement.checked).toEqual(true); | 
					
						
							|  |  |  |           expect(inputs[2].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |           expect(inputs[3].nativeElement.checked).toEqual(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           dispatchEvent(inputs[0].nativeElement, 'change'); | 
					
						
							|  |  |  |           inputs[0].nativeElement.checked = true; | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const value = fixture.debugElement.componentInstance.form.value; | 
					
						
							|  |  |  |           expect(value.food).toEqual('chicken'); | 
					
						
							|  |  |  |           expect(inputs[1].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |           expect(inputs[2].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |           expect(inputs[3].nativeElement.checked).toEqual(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           drinkCtrl.setValue('cola'); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(inputs[0].nativeElement.checked).toEqual(true); | 
					
						
							|  |  |  |           expect(inputs[1].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |           expect(inputs[2].nativeElement.checked).toEqual(true); | 
					
						
							|  |  |  |           expect(inputs[3].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should support removing controls from <type=radio>', () => { | 
					
						
							|  |  |  |           const fixture = TestBed.createComponent(FormControlRadioButtons); | 
					
						
							|  |  |  |           const showRadio = new FormControl('yes'); | 
					
						
							|  |  |  |           const form = | 
					
						
							|  |  |  |               new FormGroup({'food': new FormControl('fish'), 'drink': new FormControl('sprite')}); | 
					
						
							|  |  |  |           fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |           fixture.debugElement.componentInstance.showRadio = showRadio; | 
					
						
							|  |  |  |           showRadio.valueChanges.subscribe((change) => { | 
					
						
							|  |  |  |             (change === 'yes') ? form.addControl('food', new FormControl('fish')) : | 
					
						
							|  |  |  |                                  form.removeControl('food'); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const input = fixture.debugElement.query(By.css('[value="no"]')); | 
					
						
							|  |  |  |           dispatchEvent(input.nativeElement, 'change'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  |           expect(form.value).toEqual({drink: 'sprite'}); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 17:49:42 -07:00
										 |  |  |         it('should differentiate controls on different levels with the same name', () => { | 
					
						
							|  |  |  |           TestBed.overrideComponent(FormControlRadioButtons, { | 
					
						
							|  |  |  |             set: { | 
					
						
							|  |  |  |               template: `
 | 
					
						
							|  |  |  |               <div [formGroup]="form"> | 
					
						
							|  |  |  |                 <input type="radio" formControlName="food" value="chicken"> | 
					
						
							|  |  |  |                 <input type="radio" formControlName="food" value="fish"> | 
					
						
							|  |  |  |                 <div formGroupName="nested"> | 
					
						
							|  |  |  |                   <input type="radio" formControlName="food" value="chicken"> | 
					
						
							|  |  |  |                   <input type="radio" formControlName="food" value="fish"> | 
					
						
							|  |  |  |                 </div> | 
					
						
							|  |  |  |               </div> | 
					
						
							|  |  |  |               `
 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |           const fixture = TestBed.createComponent(FormControlRadioButtons); | 
					
						
							|  |  |  |           const form = new FormGroup({ | 
					
						
							|  |  |  |             food: new FormControl('fish'), | 
					
						
							|  |  |  |             nested: new FormGroup({food: new FormControl('fish')}) | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |           fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // model -> view
 | 
					
						
							|  |  |  |           const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |           expect(inputs[0].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |           expect(inputs[1].nativeElement.checked).toEqual(true); | 
					
						
							|  |  |  |           expect(inputs[2].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |           expect(inputs[3].nativeElement.checked).toEqual(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           dispatchEvent(inputs[0].nativeElement, 'change'); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // view -> model
 | 
					
						
							|  |  |  |           expect(form.get('food').value).toEqual('chicken'); | 
					
						
							|  |  |  |           expect(form.get('nested.food').value).toEqual('fish'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(inputs[1].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |           expect(inputs[2].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |           expect(inputs[3].nativeElement.checked).toEqual(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('custom value accessors', () => { | 
					
						
							|  |  |  |         it('should support custom value accessors', () => { | 
					
						
							|  |  |  |           const fixture = TestBed.createComponent(WrappedValueForm); | 
					
						
							|  |  |  |           fixture.debugElement.componentInstance.form = | 
					
						
							|  |  |  |               new FormGroup({'login': new FormControl('aa')}); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // model -> view
 | 
					
						
							|  |  |  |           const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |           expect(input.nativeElement.value).toEqual('!aa!'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           input.nativeElement.value = '!bb!'; | 
					
						
							|  |  |  |           dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // view -> model
 | 
					
						
							|  |  |  |           expect(fixture.debugElement.componentInstance.form.value).toEqual({'login': 'bb'}); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should support custom value accessors on non builtin input elements that fire a change event without a \'target\' property', | 
					
						
							|  |  |  |            () => { | 
					
						
							|  |  |  |              const fixture = TestBed.createComponent(MyInputForm); | 
					
						
							|  |  |  |              fixture.debugElement.componentInstance.form = | 
					
						
							|  |  |  |                  new FormGroup({'login': new FormControl('aa')}); | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              const input = fixture.debugElement.query(By.css('my-input')); | 
					
						
							|  |  |  |              expect(input.componentInstance.value).toEqual('!aa!'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              input.componentInstance.value = '!bb!'; | 
					
						
							|  |  |  |              input.componentInstance.onInput.subscribe((value: any) => { | 
					
						
							|  |  |  |                expect(fixture.debugElement.componentInstance.form.value).toEqual({'login': 'bb'}); | 
					
						
							| 
									
										
										
										
											2016-08-02 09:40:42 -07:00
										 |  |  |              }); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |              input.componentInstance.dispatchChangeEvent(); | 
					
						
							|  |  |  |            }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     describe('ngModel interactions', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should support ngModel for complex forms', fakeAsync(() => { | 
					
						
							|  |  |  |            const fixture = TestBed.createComponent(FormGroupNgModel); | 
					
						
							|  |  |  |            fixture.debugElement.componentInstance.form = | 
					
						
							|  |  |  |                new FormGroup({'login': new FormControl('')}); | 
					
						
							|  |  |  |            fixture.debugElement.componentInstance.login = 'oldValue'; | 
					
						
							| 
									
										
											  
											
												feat(forms): add modules for forms and deprecatedForms (#9859)
Closes #9732
BREAKING CHANGE:
We have removed the deprecated form directives from the built-in platform directive list, so apps are not required to package forms with their app. This also makes forms friendly to offline compilation.
Instead, we have exposed three modules:
OLD API:
- `DeprecatedFormsModule`
NEW API:
- `FormsModule`
- `ReactiveFormsModule`
If you provide one of these modules, the default forms directives and providers from that module will be available to you app-wide.  Note: You can provide both the `FormsModule` and the `ReactiveFormsModule` together if you like, but they are fully-functional separately.
**Before:**
```ts
import {disableDeprecatedForms, provideForms} from @angular/forms;
bootstrap(App, [
   disableDeprecatedForms(),
   provideForms()
]);
```
**After:**
```ts
import {DeprecatedFormsModule} from @angular/common;
bootstrap(App, {modules: [DeprecatedFormsModule] });
```
-OR-
```ts
import {FormsModule} from @angular/forms;
bootstrap(App, {modules: [FormsModule] });
```
-OR-
```ts
import {ReactiveFormsModule} from @angular/forms;
bootstrap(App, {modules: [ReactiveFormsModule] });
```
You can also choose not to provide any forms module and run your app without forms.
Or you can choose not to provide any forms module *and* provide form directives at will.  This will allow you to use the deprecatedForms API for some components and not others.
```
import {FORM_DIRECTIVES, FORM_PROVIDERS} from @angular/forms;
@Component({
   selector: some-comp,
   directives: [FORM_DIRECTIVES],
   providers: [FORM_PROVIDERS]
})
class SomeComp
```
											
										 
											2016-07-07 11:32:51 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-06-25 13:27:29 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            const input = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							|  |  |  |            expect(input.value).toEqual('oldValue'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.value = 'updatedValue'; | 
					
						
							|  |  |  |            dispatchEvent(input, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            expect(fixture.debugElement.componentInstance.login).toEqual('updatedValue'); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should support ngModel for single fields', fakeAsync(() => { | 
					
						
							|  |  |  |            const fixture = TestBed.createComponent(FormControlNgModel); | 
					
						
							|  |  |  |            fixture.debugElement.componentInstance.control = new FormControl(''); | 
					
						
							|  |  |  |            fixture.debugElement.componentInstance.login = 'oldValue'; | 
					
						
							| 
									
										
											  
											
												feat(forms): add modules for forms and deprecatedForms (#9859)
Closes #9732
BREAKING CHANGE:
We have removed the deprecated form directives from the built-in platform directive list, so apps are not required to package forms with their app. This also makes forms friendly to offline compilation.
Instead, we have exposed three modules:
OLD API:
- `DeprecatedFormsModule`
NEW API:
- `FormsModule`
- `ReactiveFormsModule`
If you provide one of these modules, the default forms directives and providers from that module will be available to you app-wide.  Note: You can provide both the `FormsModule` and the `ReactiveFormsModule` together if you like, but they are fully-functional separately.
**Before:**
```ts
import {disableDeprecatedForms, provideForms} from @angular/forms;
bootstrap(App, [
   disableDeprecatedForms(),
   provideForms()
]);
```
**After:**
```ts
import {DeprecatedFormsModule} from @angular/common;
bootstrap(App, {modules: [DeprecatedFormsModule] });
```
-OR-
```ts
import {FormsModule} from @angular/forms;
bootstrap(App, {modules: [FormsModule] });
```
-OR-
```ts
import {ReactiveFormsModule} from @angular/forms;
bootstrap(App, {modules: [ReactiveFormsModule] });
```
You can also choose not to provide any forms module and run your app without forms.
Or you can choose not to provide any forms module *and* provide form directives at will.  This will allow you to use the deprecatedForms API for some components and not others.
```
import {FORM_DIRECTIVES, FORM_PROVIDERS} from @angular/forms;
@Component({
   selector: some-comp,
   directives: [FORM_DIRECTIVES],
   providers: [FORM_PROVIDERS]
})
class SomeComp
```
											
										 
											2016-07-07 11:32:51 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-06-25 13:27:29 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            const input = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							|  |  |  |            expect(input.value).toEqual('oldValue'); | 
					
						
							| 
									
										
										
										
											2016-06-25 13:27:29 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            input.value = 'updatedValue'; | 
					
						
							|  |  |  |            dispatchEvent(input, 'input'); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            expect(fixture.debugElement.componentInstance.login).toEqual('updatedValue'); | 
					
						
							|  |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should not update the view when the value initially came from the view', fakeAsync(() => { | 
					
						
							|  |  |  |            const fixture = TestBed.createComponent(FormControlNgModel); | 
					
						
							|  |  |  |            fixture.debugElement.componentInstance.control = new FormControl(''); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            const input = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							|  |  |  |            input.value = 'aa'; | 
					
						
							|  |  |  |            input.setSelectionRange(1, 2); | 
					
						
							|  |  |  |            dispatchEvent(input, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            // selection start has not changed because we did not reset the value
 | 
					
						
							|  |  |  |            expect(input.selectionStart).toEqual(1); | 
					
						
							|  |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |     describe('validations', () => { | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should use sync validators defined in html', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(LoginIsEmptyWrapper); | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |         const form = new FormGroup({ | 
					
						
							|  |  |  |           'login': new FormControl(''), | 
					
						
							|  |  |  |           'min': new FormControl(''), | 
					
						
							|  |  |  |           'max': new FormControl(''), | 
					
						
							|  |  |  |           'pattern': new FormControl('') | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const required = fixture.debugElement.query(By.css('[required]')); | 
					
						
							|  |  |  |         const minLength = fixture.debugElement.query(By.css('[minlength]')); | 
					
						
							|  |  |  |         const maxLength = fixture.debugElement.query(By.css('[maxlength]')); | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |         const pattern = fixture.debugElement.query(By.css('[pattern]')); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         required.nativeElement.value = ''; | 
					
						
							|  |  |  |         minLength.nativeElement.value = '1'; | 
					
						
							|  |  |  |         maxLength.nativeElement.value = '1234'; | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |         pattern.nativeElement.value = '12'; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         dispatchEvent(required.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(minLength.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(maxLength.nativeElement, 'input'); | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |         dispatchEvent(pattern.nativeElement, 'input'); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         expect(form.hasError('required', ['login'])).toEqual(true); | 
					
						
							|  |  |  |         expect(form.hasError('minlength', ['min'])).toEqual(true); | 
					
						
							|  |  |  |         expect(form.hasError('maxlength', ['max'])).toEqual(true); | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |         expect(form.hasError('pattern', ['pattern'])).toEqual(true); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         expect(form.hasError('loginIsEmpty')).toEqual(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         required.nativeElement.value = '1'; | 
					
						
							|  |  |  |         minLength.nativeElement.value = '123'; | 
					
						
							|  |  |  |         maxLength.nativeElement.value = '123'; | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |         pattern.nativeElement.value = '123'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dispatchEvent(required.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(minLength.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(maxLength.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(pattern.nativeElement, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(form.valid).toEqual(true); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should use sync validators using bindings', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(ValidationBindingsForm); | 
					
						
							|  |  |  |         const form = new FormGroup({ | 
					
						
							|  |  |  |           'login': new FormControl(''), | 
					
						
							|  |  |  |           'min': new FormControl(''), | 
					
						
							|  |  |  |           'max': new FormControl(''), | 
					
						
							|  |  |  |           'pattern': new FormControl('') | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.required = true; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.minLen = 3; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.maxLen = 3; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.pattern = '.{3,}'; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const required = fixture.debugElement.query(By.css('[name=required]')); | 
					
						
							|  |  |  |         const minLength = fixture.debugElement.query(By.css('[name=minlength]')); | 
					
						
							|  |  |  |         const maxLength = fixture.debugElement.query(By.css('[name=maxlength]')); | 
					
						
							|  |  |  |         const pattern = fixture.debugElement.query(By.css('[name=pattern]')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         required.nativeElement.value = ''; | 
					
						
							|  |  |  |         minLength.nativeElement.value = '1'; | 
					
						
							|  |  |  |         maxLength.nativeElement.value = '1234'; | 
					
						
							|  |  |  |         pattern.nativeElement.value = '12'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dispatchEvent(required.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(minLength.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(maxLength.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(pattern.nativeElement, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(form.hasError('required', ['login'])).toEqual(true); | 
					
						
							|  |  |  |         expect(form.hasError('minlength', ['min'])).toEqual(true); | 
					
						
							|  |  |  |         expect(form.hasError('maxlength', ['max'])).toEqual(true); | 
					
						
							|  |  |  |         expect(form.hasError('pattern', ['pattern'])).toEqual(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         required.nativeElement.value = '1'; | 
					
						
							|  |  |  |         minLength.nativeElement.value = '123'; | 
					
						
							|  |  |  |         maxLength.nativeElement.value = '123'; | 
					
						
							|  |  |  |         pattern.nativeElement.value = '123'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dispatchEvent(required.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(minLength.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(maxLength.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(pattern.nativeElement, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(form.valid).toEqual(true); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |       it('changes on bound properties should change the validation state of the form', () => { | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |         const fixture = TestBed.createComponent(ValidationBindingsForm); | 
					
						
							|  |  |  |         const form = new FormGroup({ | 
					
						
							|  |  |  |           'login': new FormControl(''), | 
					
						
							|  |  |  |           'min': new FormControl(''), | 
					
						
							|  |  |  |           'max': new FormControl(''), | 
					
						
							|  |  |  |           'pattern': new FormControl('') | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const required = fixture.debugElement.query(By.css('[name=required]')); | 
					
						
							|  |  |  |         const minLength = fixture.debugElement.query(By.css('[name=minlength]')); | 
					
						
							|  |  |  |         const maxLength = fixture.debugElement.query(By.css('[name=maxlength]')); | 
					
						
							|  |  |  |         const pattern = fixture.debugElement.query(By.css('[name=pattern]')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         required.nativeElement.value = ''; | 
					
						
							|  |  |  |         minLength.nativeElement.value = '1'; | 
					
						
							|  |  |  |         maxLength.nativeElement.value = '1234'; | 
					
						
							|  |  |  |         pattern.nativeElement.value = '12'; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         dispatchEvent(required.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(minLength.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(maxLength.nativeElement, 'input'); | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |         dispatchEvent(pattern.nativeElement, 'input'); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |         expect(form.hasError('required', ['login'])).toEqual(false); | 
					
						
							|  |  |  |         expect(form.hasError('minlength', ['min'])).toEqual(false); | 
					
						
							|  |  |  |         expect(form.hasError('maxlength', ['max'])).toEqual(false); | 
					
						
							|  |  |  |         expect(form.hasError('pattern', ['pattern'])).toEqual(false); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         expect(form.valid).toEqual(true); | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.required = true; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.minLen = 3; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.maxLen = 3; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.pattern = '.{3,}'; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dispatchEvent(required.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(minLength.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(maxLength.nativeElement, 'input'); | 
					
						
							|  |  |  |         dispatchEvent(pattern.nativeElement, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(form.hasError('required', ['login'])).toEqual(true); | 
					
						
							|  |  |  |         expect(form.hasError('minlength', ['min'])).toEqual(true); | 
					
						
							|  |  |  |         expect(form.hasError('maxlength', ['max'])).toEqual(true); | 
					
						
							|  |  |  |         expect(form.hasError('pattern', ['pattern'])).toEqual(true); | 
					
						
							|  |  |  |         expect(form.valid).toEqual(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(required.nativeElement.getAttribute('required')).toEqual(''); | 
					
						
							|  |  |  |         expect(fixture.debugElement.componentInstance.minLen.toString()) | 
					
						
							|  |  |  |             .toEqual(minLength.nativeElement.getAttribute('minlength')); | 
					
						
							|  |  |  |         expect(fixture.debugElement.componentInstance.maxLen.toString()) | 
					
						
							|  |  |  |             .toEqual(maxLength.nativeElement.getAttribute('maxlength')); | 
					
						
							|  |  |  |         expect(fixture.debugElement.componentInstance.pattern.toString()) | 
					
						
							|  |  |  |             .toEqual(pattern.nativeElement.getAttribute('pattern')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.required = false; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.minLen = null; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.maxLen = null; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.pattern = null; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(form.hasError('required', ['login'])).toEqual(false); | 
					
						
							|  |  |  |         expect(form.hasError('minlength', ['min'])).toEqual(false); | 
					
						
							|  |  |  |         expect(form.hasError('maxlength', ['max'])).toEqual(false); | 
					
						
							|  |  |  |         expect(form.hasError('pattern', ['pattern'])).toEqual(false); | 
					
						
							|  |  |  |         expect(form.valid).toEqual(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(required.nativeElement.getAttribute('required')).toEqual(null); | 
					
						
							|  |  |  |         expect(required.nativeElement.getAttribute('minlength')).toEqual(null); | 
					
						
							|  |  |  |         expect(required.nativeElement.getAttribute('maxlength')).toEqual(null); | 
					
						
							|  |  |  |         expect(required.nativeElement.getAttribute('pattern')).toEqual(null); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |       it('should support rebound controls with rebound validators', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(ValidationBindingsForm); | 
					
						
							|  |  |  |         const form = new FormGroup({ | 
					
						
							|  |  |  |           'login': new FormControl(''), | 
					
						
							|  |  |  |           'min': new FormControl(''), | 
					
						
							|  |  |  |           'max': new FormControl(''), | 
					
						
							|  |  |  |           'pattern': new FormControl('') | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.required = true; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.minLen = 3; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.maxLen = 3; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.pattern = '.{3,}'; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const newForm = new FormGroup({ | 
					
						
							|  |  |  |           'login': new FormControl(''), | 
					
						
							|  |  |  |           'min': new FormControl(''), | 
					
						
							|  |  |  |           'max': new FormControl(''), | 
					
						
							|  |  |  |           'pattern': new FormControl('') | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = newForm; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.required = false; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.minLen = null; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.maxLen = null; | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.pattern = null; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(newForm.hasError('required', ['login'])).toEqual(false); | 
					
						
							|  |  |  |         expect(newForm.hasError('minlength', ['min'])).toEqual(false); | 
					
						
							|  |  |  |         expect(newForm.hasError('maxlength', ['max'])).toEqual(false); | 
					
						
							|  |  |  |         expect(newForm.hasError('pattern', ['pattern'])).toEqual(false); | 
					
						
							|  |  |  |         expect(newForm.valid).toEqual(true); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should use async validators defined in the html', fakeAsync(() => { | 
					
						
							|  |  |  |            const fixture = TestBed.createComponent(UniqLoginWrapper); | 
					
						
							|  |  |  |            const form = new FormGroup({'login': new FormControl('')}); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |            expect(form.pending).toEqual(true); | 
					
						
							|  |  |  |            tick(100); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |            expect(form.hasError('uniqLogin', ['login'])).toEqual(true); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            const input = fixture.debugElement.query(By.css('input')); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |            input.nativeElement.value = 'expected'; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'input'); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |            tick(100); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(form.valid).toEqual(true); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should use sync validators defined in the model', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         const form = new FormGroup({'login': new FormControl('aa', Validators.required)}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  |         expect(form.valid).toEqual(true); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         input.nativeElement.value = ''; | 
					
						
							|  |  |  |         dispatchEvent(input.nativeElement, 'input'); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         expect(form.valid).toEqual(false); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should use async validators defined in the model', fakeAsync(() => { | 
					
						
							|  |  |  |            const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |            const control = | 
					
						
							| 
									
										
										
										
											2016-06-10 11:15:59 -07:00
										 |  |  |                new FormControl('', Validators.required, uniqLoginAsyncValidator('expected')); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            const form = new FormGroup({'login': control}); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |            fixture.debugElement.componentInstance.form = form; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |            expect(form.hasError('required', ['login'])).toEqual(true); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            const input = fixture.debugElement.query(By.css('input')); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |            input.nativeElement.value = 'wrong value'; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'input'); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |            expect(form.pending).toEqual(true); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |            expect(form.hasError('uniqLogin', ['login'])).toEqual(true); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |            input.nativeElement.value = 'expected'; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'input'); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(form.valid).toEqual(true); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |     describe('errors', () => { | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should throw if a form isn\'t passed into formGroup', () => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         expect(() => fixture.detectChanges()) | 
					
						
							|  |  |  |             .toThrowError(new RegExp(`formGroup expects a FormGroup instance`)); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should throw if formControlName is used without a control container', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent(FormGroupComp, { | 
					
						
							|  |  |  |           set: { | 
					
						
							|  |  |  |             template: `
 | 
					
						
							|  |  |  |           <input type="text" formControlName="login"> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(() => fixture.detectChanges()) | 
					
						
							|  |  |  |             .toThrowError( | 
					
						
							|  |  |  |                 new RegExp(`formControlName must be used with a parent formGroup directive`)); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should throw if formControlName is used with NgForm', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent(FormGroupComp, { | 
					
						
							|  |  |  |           set: { | 
					
						
							|  |  |  |             template: `
 | 
					
						
							|  |  |  |           <form> | 
					
						
							|  |  |  |             <input type="text" formControlName="login"> | 
					
						
							|  |  |  |           </form> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(() => fixture.detectChanges()) | 
					
						
							|  |  |  |             .toThrowError( | 
					
						
							|  |  |  |                 new RegExp(`formControlName must be used with a parent formGroup directive.`)); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should throw if formControlName is used with NgModelGroup', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent(FormGroupComp, { | 
					
						
							|  |  |  |           set: { | 
					
						
							|  |  |  |             template: `
 | 
					
						
							|  |  |  |           <form> | 
					
						
							|  |  |  |             <div ngModelGroup="parent"> | 
					
						
							|  |  |  |               <input type="text" formControlName="login"> | 
					
						
							|  |  |  |             </div> | 
					
						
							|  |  |  |           </form> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(() => fixture.detectChanges()) | 
					
						
							|  |  |  |             .toThrowError( | 
					
						
							|  |  |  |                 new RegExp(`formControlName cannot be used with an ngModelGroup parent.`)); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should throw if formGroupName is used without a control container', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent(FormGroupComp, { | 
					
						
							|  |  |  |           set: { | 
					
						
							|  |  |  |             template: `
 | 
					
						
							|  |  |  |           <div formGroupName="person"> | 
					
						
							|  |  |  |             <input type="text" formControlName="login"> | 
					
						
							|  |  |  |           </div> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(() => fixture.detectChanges()) | 
					
						
							|  |  |  |             .toThrowError( | 
					
						
							|  |  |  |                 new RegExp(`formGroupName must be used with a parent formGroup directive`)); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should throw if formGroupName is used with NgForm', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent(FormGroupComp, { | 
					
						
							|  |  |  |           set: { | 
					
						
							|  |  |  |             template: `
 | 
					
						
							|  |  |  |           <form> | 
					
						
							|  |  |  |             <div formGroupName="person"> | 
					
						
							|  |  |  |               <input type="text" formControlName="login"> | 
					
						
							|  |  |  |             </div> | 
					
						
							|  |  |  |           </form> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(() => fixture.detectChanges()) | 
					
						
							|  |  |  |             .toThrowError( | 
					
						
							|  |  |  |                 new RegExp(`formGroupName must be used with a parent formGroup directive.`)); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should throw if formArrayName is used without a control container', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent(FormGroupComp, { | 
					
						
							|  |  |  |           set: { | 
					
						
							|  |  |  |             template: `
 | 
					
						
							|  |  |  |          <div formArrayName="cities"> | 
					
						
							|  |  |  |            <input type="text" formControlName="login"> | 
					
						
							|  |  |  |          </div> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(() => fixture.detectChanges()) | 
					
						
							|  |  |  |             .toThrowError( | 
					
						
							|  |  |  |                 new RegExp(`formArrayName must be used with a parent formGroup directive`)); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should throw if ngModel is used alone under formGroup', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent(FormGroupComp, { | 
					
						
							|  |  |  |           set: { | 
					
						
							|  |  |  |             template: `
 | 
					
						
							|  |  |  |          <div [formGroup]="myGroup"> | 
					
						
							|  |  |  |            <input type="text" [(ngModel)]="data"> | 
					
						
							|  |  |  |          </div> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.myGroup = new FormGroup({}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(() => fixture.detectChanges()) | 
					
						
							|  |  |  |             .toThrowError(new RegExp( | 
					
						
							|  |  |  |                 `ngModel cannot be used to register form controls with a parent formGroup directive.`)); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-07-26 10:08:46 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should not throw if ngModel is used alone under formGroup with standalone: true', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent(FormGroupComp, { | 
					
						
							|  |  |  |           set: { | 
					
						
							|  |  |  |             template: `
 | 
					
						
							|  |  |  |          <div [formGroup]="myGroup"> | 
					
						
							|  |  |  |             <input type="text" [(ngModel)]="data" [ngModelOptions]="{standalone: true}"> | 
					
						
							|  |  |  |          </div> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.myGroup = new FormGroup({}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(() => fixture.detectChanges()).not.toThrowError(); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-07-26 10:08:46 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should throw if ngModel is used alone with formGroupName', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent(FormGroupComp, { | 
					
						
							|  |  |  |           set: { | 
					
						
							|  |  |  |             template: `
 | 
					
						
							|  |  |  |           <div [formGroup]="myGroup"> | 
					
						
							| 
									
										
										
										
											2016-07-27 10:59:40 -07:00
										 |  |  |             <div formGroupName="person"> | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |               <input type="text" [(ngModel)]="data"> | 
					
						
							| 
									
										
										
										
											2016-07-27 10:59:40 -07:00
										 |  |  |             </div> | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |           </div> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         const myGroup = new FormGroup({person: new FormGroup({})}); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.myGroup = new FormGroup({person: new FormGroup({})}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(() => fixture.detectChanges()) | 
					
						
							|  |  |  |             .toThrowError(new RegExp( | 
					
						
							|  |  |  |                 `ngModel cannot be used to register form controls with a parent formGroupName or formArrayName directive.`)); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should throw if ngModelGroup is used with formGroup', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent(FormGroupComp, { | 
					
						
							|  |  |  |           set: { | 
					
						
							|  |  |  |             template: `
 | 
					
						
							|  |  |  |           <div [formGroup]="myGroup"> | 
					
						
							|  |  |  |             <div ngModelGroup="person"> | 
					
						
							| 
									
										
										
										
											2016-07-27 10:59:40 -07:00
										 |  |  |               <input type="text" [(ngModel)]="data"> | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |             </div> | 
					
						
							|  |  |  |           </div> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.myGroup = new FormGroup({}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(() => fixture.detectChanges()) | 
					
						
							|  |  |  |             .toThrowError( | 
					
						
							|  |  |  |                 new RegExp(`ngModelGroup cannot be used with a parent formGroup directive`)); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should throw if radio button name does not match formControlName attr', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent(FormGroupComp, { | 
					
						
							|  |  |  |           set: { | 
					
						
							|  |  |  |             template: `
 | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |           <form [formGroup]="form">hav | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |             <input type="radio" formControlName="food" name="drink" value="chicken"> | 
					
						
							|  |  |  |           </form> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(FormGroupComp); | 
					
						
							|  |  |  |         fixture.debugElement.componentInstance.form = | 
					
						
							|  |  |  |             new FormGroup({'food': new FormControl('fish')}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(() => fixture.detectChanges()) | 
					
						
							|  |  |  |             .toThrowError(new RegExp('If you define both a name and a formControlName')); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-26 10:08:46 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Directive({ | 
					
						
							|  |  |  |   selector: '[wrapped-value]', | 
					
						
							|  |  |  |   host: {'(input)': 'handleOnInput($event.target.value)', '[value]': 'value'} | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class WrappedValue implements ControlValueAccessor { | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |   value: any; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   onChange: Function; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   constructor(cd: NgControl) { cd.valueAccessor = this; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |   writeValue(value: any) { this.value = `!${value}!`; } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |   registerOnChange(fn: (value: any) => void) { this.onChange = fn; } | 
					
						
							|  |  |  |   registerOnTouched(fn: any) {} | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |   handleOnInput(value: any) { this.onChange(value.substring(1, value.length - 1)); } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | @Component({selector: 'my-input', template: ''}) | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | class MyInput implements ControlValueAccessor { | 
					
						
							| 
									
										
										
										
											2016-06-10 19:10:17 -07:00
										 |  |  |   @Output('input') onInput = new EventEmitter(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   value: string; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   constructor(cd: NgControl) { cd.valueAccessor = this; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |   writeValue(value: any) { this.value = `!${value}!`; } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |   registerOnChange(fn: (value: any) => void) { this.onInput.subscribe({next: fn}); } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |   registerOnTouched(fn: any) {} | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-02 15:53:34 -07:00
										 |  |  |   dispatchChangeEvent() { this.onInput.emit(this.value.substring(1, this.value.length - 1)); } | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function uniqLoginAsyncValidator(expectedValue: string) { | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |   return (c: AbstractControl) => { | 
					
						
							| 
									
										
										
										
											2016-08-02 15:53:34 -07:00
										 |  |  |     var resolve: (result: any) => void; | 
					
						
							|  |  |  |     var promise = new Promise(res => { resolve = res; }); | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |     var res = (c.value == expectedValue) ? null : {'uniqLogin': true}; | 
					
						
							| 
									
										
										
										
											2016-08-02 15:53:34 -07:00
										 |  |  |     resolve(res); | 
					
						
							|  |  |  |     return promise; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-10 11:15:59 -07:00
										 |  |  | function loginIsEmptyGroupValidator(c: FormGroup) { | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   return c.controls['login'].value == '' ? {'loginIsEmpty': true} : null; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Directive({ | 
					
						
							|  |  |  |   selector: '[login-is-empty-validator]', | 
					
						
							| 
									
										
										
										
											2016-07-30 19:18:14 -07:00
										 |  |  |   providers: [{provide: NG_VALIDATORS, useValue: loginIsEmptyGroupValidator, multi: true}] | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | class LoginIsEmptyValidator { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Directive({ | 
					
						
							|  |  |  |   selector: '[uniq-login-validator]', | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  |   providers: [{ | 
					
						
							|  |  |  |     provide: NG_ASYNC_VALIDATORS, | 
					
						
							|  |  |  |     useExisting: forwardRef(() => UniqLoginValidator), | 
					
						
							|  |  |  |     multi: true | 
					
						
							|  |  |  |   }] | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | class UniqLoginValidator implements Validator { | 
					
						
							| 
									
										
										
										
											2016-06-08 17:08:59 -07:00
										 |  |  |   @Input('uniq-login-validator') expected: any /** TODO #9100 */; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |   validate(c: AbstractControl) { return uniqLoginAsyncValidator(this.expected)(c); } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function sortedClassList(el: HTMLElement) { | 
					
						
							|  |  |  |   var l = getDOM().classList(el); | 
					
						
							|  |  |  |   ListWrapper.sort(l); | 
					
						
							|  |  |  |   return l; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |   selector: 'form-control-comp', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <input type="text" [formControl]="control"> | 
					
						
							|  |  |  |   `
 | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | }) | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | class FormControlComp { | 
					
						
							|  |  |  |   control: FormControl; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'form-group-comp', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <form [formGroup]="form" (ngSubmit)="data='submitted'"> | 
					
						
							|  |  |  |       <input type="text" formControlName="login"> | 
					
						
							|  |  |  |     </form> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class FormGroupComp { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							|  |  |  |   data: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'nested-form-group-comp', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <form [formGroup]="form"> | 
					
						
							|  |  |  |       <div formGroupName="signin" login-is-empty-validator> | 
					
						
							|  |  |  |         <input formControlName="login"> | 
					
						
							|  |  |  |         <input formControlName="password"> | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |       <input *ngIf="form.contains('email')" formControlName="email"> | 
					
						
							|  |  |  |     </form> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NestedFormGroupComp { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'form-control-number-input', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <input type="number" [formControl]="control"> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class FormControlNumberInput { | 
					
						
							|  |  |  |   control: FormControl; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'form-control-radio-buttons', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |   <form [formGroup]="form" *ngIf="showRadio.value === 'yes'"> | 
					
						
							|  |  |  |     <input type="radio" formControlName="food" value="chicken"> | 
					
						
							|  |  |  |     <input type="radio" formControlName="food" value="fish"> | 
					
						
							|  |  |  |     <input type="radio" formControlName="drink" value="cola"> | 
					
						
							|  |  |  |     <input type="radio" formControlName="drink" value="sprite"> | 
					
						
							|  |  |  |   </form> | 
					
						
							|  |  |  |   <input type="radio" [formControl]="showRadio" value="yes"> | 
					
						
							|  |  |  |   <input type="radio" [formControl]="showRadio" value="no"> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class FormControlRadioButtons { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							|  |  |  |   showRadio = new FormControl('yes'); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'form-array-comp', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <div [formGroup]="form"> | 
					
						
							|  |  |  |       <div formArrayName="cities"> | 
					
						
							|  |  |  |         <div *ngFor="let city of cityArray.controls; let i=index"> | 
					
						
							|  |  |  |           <input [formControlName]="i"> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |      </div> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class FormArrayComp { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							|  |  |  |   cityArray: FormArray; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'form-array-nested-group', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |      <div [formGroup]="form"> | 
					
						
							|  |  |  |       <div formArrayName="cities"> | 
					
						
							|  |  |  |         <div *ngFor="let city of cityArray.controls; let i=index" [formGroupName]="i"> | 
					
						
							|  |  |  |           <input formControlName="town"> | 
					
						
							|  |  |  |           <input formControlName="state"> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |      </div> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class FormArrayNestedGroup { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							|  |  |  |   cityArray: FormArray; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'form-control-name-select', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <div [formGroup]="form"> | 
					
						
							|  |  |  |       <select formControlName="city"> | 
					
						
							|  |  |  |         <option *ngFor="let c of cities" [value]="c"></option> | 
					
						
							|  |  |  |       </select> | 
					
						
							|  |  |  |     </div> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class FormControlNameSelect { | 
					
						
							|  |  |  |   cities = ['SF', 'NY']; | 
					
						
							|  |  |  |   form = new FormGroup({city: new FormControl('SF')}); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'wrapped-value-form', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |    <div [formGroup]="form"> | 
					
						
							|  |  |  |     <input type="text" formControlName="login" wrapped-value> | 
					
						
							|  |  |  |   </div> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class WrappedValueForm { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'my-input-form', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |    <div [formGroup]="form"> | 
					
						
							|  |  |  |       <my-input formControlName="login"></my-input> | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |    </div> | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class MyInputForm { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'form-group-ng-model', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |   <div [formGroup]="form"> | 
					
						
							|  |  |  |     <input type="text" formControlName="login" [(ngModel)]="login"> | 
					
						
							|  |  |  |    </div> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class FormGroupNgModel { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							|  |  |  |   login: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'form-control-ng-model', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <input type="text" [formControl]="control" [(ngModel)]="login"> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class FormControlNgModel { | 
					
						
							|  |  |  |   control: FormControl; | 
					
						
							|  |  |  |   login: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'login-is-empty-wrapper', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <div [formGroup]="form" login-is-empty-validator> | 
					
						
							|  |  |  |       <input type="text" formControlName="login" required> | 
					
						
							|  |  |  |       <input type="text" formControlName="min" minlength="3"> | 
					
						
							|  |  |  |       <input type="text" formControlName="max" maxlength="3"> | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |       <input type="text" formControlName="pattern" pattern=".{3,}"> | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |    </div> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class LoginIsEmptyWrapper { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'validation-bindings-form', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <div [formGroup]="form"> | 
					
						
							|  |  |  |       <input name="required" type="text" formControlName="login" [required]="required"> | 
					
						
							|  |  |  |       <input name="minlength" type="text" formControlName="min" [minlength]="minLen"> | 
					
						
							|  |  |  |       <input name="maxlength" type="text" formControlName="max" [maxlength]="maxLen"> | 
					
						
							|  |  |  |       <input name="pattern" type="text" formControlName="pattern" [pattern]="pattern"> | 
					
						
							|  |  |  |    </div> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class ValidationBindingsForm { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							|  |  |  |   required: boolean; | 
					
						
							|  |  |  |   minLen: number; | 
					
						
							|  |  |  |   maxLen: number; | 
					
						
							|  |  |  |   pattern: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'uniq-login-wrapper', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |   <div [formGroup]="form"> | 
					
						
							|  |  |  |     <input type="text" formControlName="login" uniq-login-validator="expected"> | 
					
						
							|  |  |  |   </div> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class UniqLoginWrapper { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | } |