| 
									
										
										
										
											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
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-26 11:24:47 -07:00
										 |  |  | import {Component, Directive, Input, Type, forwardRef} from '@angular/core'; | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  | import {ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/testing'; | 
					
						
							| 
									
										
										
										
											2017-07-26 11:24:47 -07:00
										 |  |  | import {AbstractControl, AsyncValidator, AsyncValidatorFn, COMPOSITION_BUFFER_MODE, FormArray, FormControl, FormGroup, FormGroupDirective, FormsModule, NG_ASYNC_VALIDATORS, NG_VALIDATORS, ReactiveFormsModule, 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'; | 
					
						
							| 
									
										
										
										
											2017-03-02 12:12:46 -08:00
										 |  |  | import {dispatchEvent} from '@angular/platform-browser/testing/src/browser_util'; | 
					
						
							| 
									
										
										
										
											2017-03-16 10:15:17 -07:00
										 |  |  | import {timer} from 'rxjs/observable/timer'; | 
					
						
							|  |  |  | import {_do} from 'rxjs/operator/do'; | 
					
						
							| 
									
										
										
										
											2017-07-26 11:24:47 -07:00
										 |  |  | import {MyInput, MyInputForm} from './value_accessor_integration_spec'; | 
					
						
							| 
									
										
										
										
											2016-06-08 16:38:52 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-12-16 02:07:26 +01:00
										 |  |  |     function initTest<T>(component: Type<T>, ...directives: Type<any>[]): ComponentFixture<T> { | 
					
						
							|  |  |  |       TestBed.configureTestingModule( | 
					
						
							|  |  |  |           {declarations: [component, ...directives], imports: [FormsModule, ReactiveFormsModule]}); | 
					
						
							|  |  |  |       return TestBed.createComponent(component); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormControlComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const control = new FormControl('old value'); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.control = control; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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)', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = new FormGroup({'login': new FormControl('loginValue')}); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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-12-12 22:17:42 +03:00
										 |  |  |       it('should add novalidate by default to form', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-12-12 22:17:42 +03:00
										 |  |  |         fixture.componentInstance.form = new FormGroup({'login': new FormControl('loginValue')}); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const form = fixture.debugElement.query(By.css('form')); | 
					
						
							|  |  |  |         expect(form.nativeElement.getAttribute('novalidate')).toEqual(''); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('work with formGroups (view -> model)', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const form = new FormGroup({'login': new FormControl('oldValue')}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-26 11:24:47 -07:00
										 |  |  |     describe('re-bound form groups', () => { | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it('should update DOM elements initially', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = new FormGroup({'login': new FormControl('oldValue')}); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = new FormGroup({'login': new FormControl('newValue')}); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = new FormGroup({'login': new FormControl('oldValue')}); | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const newForm = new FormGroup({'login': new FormControl('newValue')}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = newForm; | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |         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 update nested form group model when UI changes', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(NestedFormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = new FormGroup( | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |             {'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')}) | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = newForm; | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |         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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(LoginIsEmptyWrapper, LoginIsEmptyValidator); | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |         const form = new FormGroup({ | 
					
						
							|  |  |  |           'login': new FormControl(''), | 
					
						
							|  |  |  |           'min': new FormControl(''), | 
					
						
							|  |  |  |           'max': new FormControl(''), | 
					
						
							|  |  |  |           'pattern': new FormControl('') | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |         expect(form.get('login') !.errors).toEqual({required: true}); | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const newForm = new FormGroup({ | 
					
						
							|  |  |  |           'login': new FormControl(''), | 
					
						
							|  |  |  |           'min': new FormControl(''), | 
					
						
							|  |  |  |           'max': new FormControl(''), | 
					
						
							|  |  |  |           'pattern': new FormControl('') | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = newForm; | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |         expect(newForm.get('login') !.errors).toEqual({required: true}); | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |       it('should pick up dir validators from nested form groups', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(NestedFormGroupComp, LoginIsEmptyValidator); | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |         const form = new FormGroup({ | 
					
						
							|  |  |  |           'signin': | 
					
						
							|  |  |  |               new FormGroup({'login': new FormControl(''), 'password': new FormControl('')}) | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |         fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |         expect(form.get('signin') !.valid).toBe(false); | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const newForm = new FormGroup({ | 
					
						
							|  |  |  |           'signin': | 
					
						
							|  |  |  |               new FormGroup({'login': new FormControl(''), 'password': new FormControl('')}) | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = newForm; | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |         expect(form.get('signin') !.valid).toBe(false); | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should strip named controls that are not found', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(NestedFormGroupComp, LoginIsEmptyValidator); | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |         const form = new FormGroup({ | 
					
						
							|  |  |  |           'signin': | 
					
						
							|  |  |  |               new FormGroup({'login': new FormControl(''), 'password': new FormControl('')}) | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |         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('')}) | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = newForm; | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         emailInput = fixture.debugElement.query(By.css('[formControlName="email"]')); | 
					
						
							|  |  |  |         expect(emailInput).toBe(null); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should strip array controls that are not found', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormArrayComp); | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |         const cityArray = new FormArray([new FormControl('SF'), new FormControl('NY')]); | 
					
						
							|  |  |  |         const form = new FormGroup({cities: cityArray}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.componentInstance.cityArray = cityArray; | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |         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}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = newForm; | 
					
						
							|  |  |  |         fixture.componentInstance.cityArray = newArr; | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |         expect(inputs[2]).not.toBeDefined(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |       describe('nested control rebinding', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should attach dir to control when leaf control changes', () => { | 
					
						
							|  |  |  |           const form = new FormGroup({'login': new FormControl('oldValue')}); | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |           const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |           fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           form.removeControl('login'); | 
					
						
							|  |  |  |           form.addControl('login', new FormControl('newValue')); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |           expect(input.nativeElement.value).toEqual('newValue'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           input.nativeElement.value = 'user input'; | 
					
						
							|  |  |  |           dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(form.value).toEqual({login: 'user input'}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           form.setValue({login: 'Carson'}); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  |           expect(input.nativeElement.value).toEqual('Carson'); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should attach dirs to all child controls when group control changes', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |           const fixture = initTest(NestedFormGroupComp, LoginIsEmptyValidator); | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |           const form = new FormGroup({ | 
					
						
							|  |  |  |             signin: new FormGroup( | 
					
						
							|  |  |  |                 {login: new FormControl('oldLogin'), password: new FormControl('oldPassword')}) | 
					
						
							|  |  |  |           }); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |           fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           form.removeControl('signin'); | 
					
						
							|  |  |  |           form.addControl( | 
					
						
							|  |  |  |               'signin', | 
					
						
							|  |  |  |               new FormGroup( | 
					
						
							|  |  |  |                   {login: new FormControl('newLogin'), password: new FormControl('newPassword')})); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |           expect(inputs[0].nativeElement.value).toEqual('newLogin'); | 
					
						
							|  |  |  |           expect(inputs[1].nativeElement.value).toEqual('newPassword'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           inputs[0].nativeElement.value = 'user input'; | 
					
						
							|  |  |  |           dispatchEvent(inputs[0].nativeElement, 'input'); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(form.value).toEqual({signin: {login: 'user input', password: 'newPassword'}}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           form.setValue({signin: {login: 'Carson', password: 'Drew'}}); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  |           expect(inputs[0].nativeElement.value).toEqual('Carson'); | 
					
						
							|  |  |  |           expect(inputs[1].nativeElement.value).toEqual('Drew'); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should attach dirs to all present child controls when array control changes', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |           const fixture = initTest(FormArrayComp); | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |           const cityArray = new FormArray([new FormControl('SF'), new FormControl('NY')]); | 
					
						
							|  |  |  |           const form = new FormGroup({cities: cityArray}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |           fixture.componentInstance.form = form; | 
					
						
							|  |  |  |           fixture.componentInstance.cityArray = cityArray; | 
					
						
							| 
									
										
										
										
											2016-09-02 15:57:35 -07:00
										 |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           form.removeControl('cities'); | 
					
						
							|  |  |  |           form.addControl('cities', new FormArray([new FormControl('LA')])); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |           expect(input.nativeElement.value).toEqual('LA'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           input.nativeElement.value = 'MTV'; | 
					
						
							|  |  |  |           dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           expect(form.value).toEqual({cities: ['MTV']}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           form.setValue({cities: ['LA']}); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  |           expect(input.nativeElement.value).toEqual('LA'); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -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('form arrays', () => { | 
					
						
							|  |  |  |       it('should support form arrays', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormArrayComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const cityArray = new FormArray([new FormControl('SF'), new FormControl('NY')]); | 
					
						
							|  |  |  |         const form = new FormGroup({cities: cityArray}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.componentInstance.cityArray = cityArray; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormArrayComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const cityArray = new FormArray([new FormControl('SF'), new FormControl('NY')]); | 
					
						
							|  |  |  |         const form = new FormGroup({cities: cityArray}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.componentInstance.cityArray = cityArray; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormArrayNestedGroup); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.componentInstance.cityArray = cityArray; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const login = new FormControl('oldValue'); | 
					
						
							|  |  |  |         const form = new FormGroup({'login': login}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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', | 
					
						
							|  |  |  |            () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |              const fixture = initTest(FormControlComp); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |              const control = new FormControl({value: 'some value', disabled: true}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |              fixture.componentInstance.control = control; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |              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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |           const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |           const control = new FormControl({value: 'some value', disabled: true}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |           fixture.componentInstance.form = new FormGroup({login: control}); | 
					
						
							|  |  |  |           fixture.componentInstance.control = control; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |           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', | 
					
						
							|  |  |  |            () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |              const fixture = initTest(FormControlComp); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |              const control = new FormControl('some value'); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |              fixture.componentInstance.control = control; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |              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', | 
					
						
							|  |  |  |            () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |              const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |              const form = new FormGroup({'login': new FormControl('login')}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |              fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |              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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |           const fixture = initTest(MyInputForm, MyInput); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |           const control = new FormControl('some value'); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |           fixture.componentInstance.form = new FormGroup({login: control}); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |           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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const login = new FormControl('oldValue'); | 
					
						
							|  |  |  |         const form = new FormGroup({'login': login}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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', () => { | 
					
						
							| 
									
										
										
										
											2016-10-11 23:49:36 +01:00
										 |  |  |       it('should emit ngSubmit event with the original submit event on submit', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = new FormGroup({'login': new FormControl('loginValue')}); | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |         fixture.componentInstance.event = null !; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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(); | 
					
						
							| 
									
										
										
										
											2016-10-11 23:49:36 +01:00
										 |  |  |         expect(fixture.componentInstance.event.type).toEqual('submit'); | 
					
						
							| 
									
										
										
										
											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 mark formGroup as submitted on submit event', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = new FormGroup({'login': new FormControl('loginValue')}); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const login = new FormControl('some value'); | 
					
						
							|  |  |  |         const form = new FormGroup({'login': login}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const login = new FormControl('some value'); | 
					
						
							|  |  |  |         const form = new FormGroup({'login': login}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const login = new FormControl('oldValue'); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = new FormGroup({'login': login}); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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 ', | 
					
						
							|  |  |  |          () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            const login = new FormControl('oldValue'); | 
					
						
							|  |  |  |            const form = new FormGroup({'login': login}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormControlComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const control = new FormControl('', Validators.required); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.control = control; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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-10-19 18:56:31 +02:00
										 |  |  |       it('should work with single fields and async validators', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(FormControlComp); | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |            const control = new FormControl('', null !, uniqLoginAsyncValidator('good')); | 
					
						
							| 
									
										
										
										
											2016-10-19 18:56:31 +02:00
										 |  |  |            fixture.debugElement.componentInstance.control = control; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const input = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							|  |  |  |            expect(sortedClassList(input)).toEqual(['ng-pending', 'ng-pristine', 'ng-untouched']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            dispatchEvent(input, 'blur'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            expect(sortedClassList(input)).toEqual(['ng-pending', 'ng-pristine', 'ng-touched']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.value = 'good'; | 
					
						
							|  |  |  |            dispatchEvent(input, 'input'); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should work with single fields that combines async and sync validators', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(FormControlComp); | 
					
						
							| 
									
										
										
										
											2016-10-19 18:56:31 +02:00
										 |  |  |            const control = | 
					
						
							|  |  |  |                new FormControl('', Validators.required, uniqLoginAsyncValidator('good')); | 
					
						
							|  |  |  |            fixture.debugElement.componentInstance.control = control; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const input = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							|  |  |  |            expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            dispatchEvent(input, 'blur'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.value = 'bad'; | 
					
						
							|  |  |  |            dispatchEvent(input, 'input'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-pending', 'ng-touched']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-invalid', 'ng-touched']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.value = 'good'; | 
					
						
							|  |  |  |            dispatchEvent(input, 'input'); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should work with single fields in parent forms', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const form = new FormGroup({'login': new FormControl('', Validators.required)}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const form = new FormGroup({'login': new FormControl('', Validators.required)}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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('ngModel interactions', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should support ngModel for complex forms', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(FormGroupNgModel); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.form = new FormGroup({'login': new FormControl('')}); | 
					
						
							|  |  |  |            fixture.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(); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            expect(fixture.componentInstance.login).toEqual('updatedValue'); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should support ngModel for single fields', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(FormControlNgModel); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.control = new FormControl(''); | 
					
						
							|  |  |  |            fixture.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-09-09 12:04:38 -07:00
										 |  |  |            expect(fixture.componentInstance.login).toEqual('updatedValue'); | 
					
						
							| 
									
										
										
										
											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 not update the view when the value initially came from the view', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(FormControlNgModel); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.control = new FormControl(''); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            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-12-10 13:44:04 +03:00
										 |  |  |       it('required validator should validate checkbox', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormControlCheckboxRequiredValidator); | 
					
						
							| 
									
										
										
										
											2016-12-10 13:44:04 +03:00
										 |  |  |         const control = new FormControl(false, Validators.requiredTrue); | 
					
						
							|  |  |  |         fixture.componentInstance.control = control; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const checkbox = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         expect(checkbox.nativeElement.checked).toBe(false); | 
					
						
							|  |  |  |         expect(control.hasError('required')).toEqual(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         checkbox.nativeElement.checked = true; | 
					
						
							|  |  |  |         dispatchEvent(checkbox.nativeElement, 'change'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(checkbox.nativeElement.checked).toBe(true); | 
					
						
							|  |  |  |         expect(control.hasError('required')).toEqual(false); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       it('should use sync validators defined in html', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(LoginIsEmptyWrapper, LoginIsEmptyValidator); | 
					
						
							| 
									
										
										
										
											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-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(ValidationBindingsForm); | 
					
						
							| 
									
										
										
										
											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-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.componentInstance.required = true; | 
					
						
							|  |  |  |         fixture.componentInstance.minLen = 3; | 
					
						
							|  |  |  |         fixture.componentInstance.maxLen = 3; | 
					
						
							|  |  |  |         fixture.componentInstance.pattern = '.{3,}'; | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |         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-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(ValidationBindingsForm); | 
					
						
							| 
									
										
										
										
											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-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |         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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.required = true; | 
					
						
							|  |  |  |         fixture.componentInstance.minLen = 3; | 
					
						
							|  |  |  |         fixture.componentInstance.maxLen = 3; | 
					
						
							|  |  |  |         fixture.componentInstance.pattern = '.{3,}'; | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |         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(''); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         expect(fixture.componentInstance.minLen.toString()) | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |             .toEqual(minLength.nativeElement.getAttribute('minlength')); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         expect(fixture.componentInstance.maxLen.toString()) | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |             .toEqual(maxLength.nativeElement.getAttribute('maxlength')); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         expect(fixture.componentInstance.pattern.toString()) | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |             .toEqual(pattern.nativeElement.getAttribute('pattern')); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.required = false; | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |         fixture.componentInstance.minLen = null !; | 
					
						
							|  |  |  |         fixture.componentInstance.maxLen = null !; | 
					
						
							|  |  |  |         fixture.componentInstance.pattern = null !; | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  |         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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(ValidationBindingsForm); | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |         const form = new FormGroup({ | 
					
						
							|  |  |  |           'login': new FormControl(''), | 
					
						
							|  |  |  |           'min': new FormControl(''), | 
					
						
							|  |  |  |           'max': new FormControl(''), | 
					
						
							|  |  |  |           'pattern': new FormControl('') | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							|  |  |  |         fixture.componentInstance.required = true; | 
					
						
							|  |  |  |         fixture.componentInstance.minLen = 3; | 
					
						
							|  |  |  |         fixture.componentInstance.maxLen = 3; | 
					
						
							|  |  |  |         fixture.componentInstance.pattern = '.{3,}'; | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const newForm = new FormGroup({ | 
					
						
							|  |  |  |           'login': new FormControl(''), | 
					
						
							|  |  |  |           'min': new FormControl(''), | 
					
						
							|  |  |  |           'max': new FormControl(''), | 
					
						
							|  |  |  |           'pattern': new FormControl('') | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = newForm; | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.required = false; | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |         fixture.componentInstance.minLen = null !; | 
					
						
							|  |  |  |         fixture.componentInstance.maxLen = null !; | 
					
						
							|  |  |  |         fixture.componentInstance.pattern = null !; | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |         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(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(UniqLoginWrapper, UniqLoginValidator); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            const form = new FormGroup({'login': new FormControl('')}); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const form = new FormGroup({'login': new FormControl('aa', Validators.required)}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         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(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |            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-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.form = form; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |            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-12-04 01:17:09 +03:00
										 |  |  |       it('async validator should not override result of sync validator', fakeAsync(() => { | 
					
						
							|  |  |  |            const fixture = initTest(FormGroupComp); | 
					
						
							|  |  |  |            const control = | 
					
						
							|  |  |  |                new FormControl('', Validators.required, uniqLoginAsyncValidator('expected', 100)); | 
					
						
							|  |  |  |            fixture.componentInstance.form = new FormGroup({'login': control}); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(control.hasError('required')).toEqual(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |            input.nativeElement.value = 'expected'; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(control.pending).toEqual(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.nativeElement.value = ''; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  |            tick(110); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(control.valid).toEqual(false); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-16 10:15:17 -07:00
										 |  |  |       it('should cancel observable properly between validation runs', fakeAsync(() => { | 
					
						
							|  |  |  |            const fixture = initTest(FormControlComp); | 
					
						
							|  |  |  |            const resultArr: number[] = []; | 
					
						
							|  |  |  |            fixture.componentInstance.control = | 
					
						
							| 
									
										
										
										
											2017-04-17 11:13:30 -07:00
										 |  |  |                new FormControl('', null !, observableValidator(resultArr)); | 
					
						
							| 
									
										
										
										
											2017-03-16 10:15:17 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(100); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(resultArr.length).toEqual(1, `Expected source observable to emit once on init.`); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |            input.nativeElement.value = 'a'; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.nativeElement.value = 'aa'; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            tick(100); | 
					
						
							|  |  |  |            expect(resultArr.length) | 
					
						
							|  |  |  |                .toEqual(2, `Expected original observable to be canceled on the next value change.`) | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(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"> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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"> | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |          </div>`
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.myGroup = new FormGroup({}); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.myGroup = new FormGroup({}); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |         const myGroup = new FormGroup({person: new FormGroup({})}); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.myGroup = new FormGroup({person: new FormGroup({})}); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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> | 
					
						
							|  |  |  |         `
 | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.myGroup = new FormGroup({}); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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"> | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |           </form>`
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(FormGroupComp); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |         fixture.componentInstance.form = new FormGroup({'food': new FormControl('fish')}); | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         expect(() => fixture.detectChanges()) | 
					
						
							|  |  |  |             .toThrowError(new RegExp('If you define both a name and a formControlName')); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-26 10:08:46 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
											  
											
												fix(forms): make composition event buffering configurable (#15256)
This commit fixes a regression where `ngModel` no longer syncs
letter by letter on Android devices, and instead syncs at the
end of every word. This broke when we introduced buffering of
IME events so IMEs like Pinyin keyboards or Katakana keyboards
wouldn't display composition strings. Unfortunately, iOS devices
and Android devices have opposite event behavior. Whereas iOS
devices fire composition events for IME keyboards only, Android
fires composition events for Latin-language keyboards. For
this reason, languages like English don't work as expected on
Android if we always buffer. So to support both platforms,
composition string buffering will only be turned on by default
for non-Android devices.
However, we have also added a `COMPOSITION_BUFFER_MODE` token
to make this configurable by the application. In some cases, apps
might might still want to receive intermediate values. For example,
some inputs begin searching based on Latin letters before a
character selection is made.
As a provider, this is fairly flexible. If you want to turn
composition buffering off, simply provide the token at the top
level:
```ts
providers: [
   {provide: COMPOSITION_BUFFER_MODE, useValue: false}
]
```
Or, if you want to change the mode  based on locale or platform,
you can use a factory:
```ts
import {shouldUseBuffering} from 'my/lib';
....
providers: [
   {provide: COMPOSITION_BUFFER_MODE, useFactory: shouldUseBuffering}
]
```
Closes #15079.
PR Close #15256
											
										 
											2017-03-20 17:38:33 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     describe('IME events', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should determine IME event handling depending on platform by default', () => { | 
					
						
							|  |  |  |         const fixture = initTest(FormControlComp); | 
					
						
							|  |  |  |         fixture.componentInstance.control = new FormControl('oldValue'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const inputEl = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         const inputNativeEl = inputEl.nativeElement; | 
					
						
							|  |  |  |         expect(inputNativeEl.value).toEqual('oldValue'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         inputEl.triggerEventHandler('compositionstart', null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         inputNativeEl.value = 'updatedValue'; | 
					
						
							|  |  |  |         dispatchEvent(inputNativeEl, 'input'); | 
					
						
							|  |  |  |         const isAndroid = /android (\d+)/.test(getDOM().getUserAgent().toLowerCase()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (isAndroid) { | 
					
						
							|  |  |  |           // On Android, values should update immediately
 | 
					
						
							|  |  |  |           expect(fixture.componentInstance.control.value).toEqual('updatedValue'); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           // On other platforms, values should wait for compositionend
 | 
					
						
							|  |  |  |           expect(fixture.componentInstance.control.value).toEqual('oldValue'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           inputEl.triggerEventHandler('compositionend', {target: {value: 'updatedValue'}}); | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  |           expect(fixture.componentInstance.control.value).toEqual('updatedValue'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should hold IME events until compositionend if composition mode', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent( | 
					
						
							|  |  |  |             FormControlComp, | 
					
						
							|  |  |  |             {set: {providers: [{provide: COMPOSITION_BUFFER_MODE, useValue: true}]}}); | 
					
						
							|  |  |  |         const fixture = initTest(FormControlComp); | 
					
						
							|  |  |  |         fixture.componentInstance.control = new FormControl('oldValue'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const inputEl = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         const inputNativeEl = inputEl.nativeElement; | 
					
						
							|  |  |  |         expect(inputNativeEl.value).toEqual('oldValue'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         inputEl.triggerEventHandler('compositionstart', null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         inputNativeEl.value = 'updatedValue'; | 
					
						
							|  |  |  |         dispatchEvent(inputNativeEl, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // should not update when compositionstart
 | 
					
						
							|  |  |  |         expect(fixture.componentInstance.control.value).toEqual('oldValue'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         inputEl.triggerEventHandler('compositionend', {target: {value: 'updatedValue'}}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // should update when compositionend
 | 
					
						
							|  |  |  |         expect(fixture.componentInstance.control.value).toEqual('updatedValue'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should work normally with composition events if composition mode is off', () => { | 
					
						
							|  |  |  |         TestBed.overrideComponent( | 
					
						
							|  |  |  |             FormControlComp, | 
					
						
							|  |  |  |             {set: {providers: [{provide: COMPOSITION_BUFFER_MODE, useValue: false}]}}); | 
					
						
							|  |  |  |         const fixture = initTest(FormControlComp); | 
					
						
							|  |  |  |         fixture.componentInstance.control = new FormControl('oldValue'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const inputEl = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |         const inputNativeEl = inputEl.nativeElement; | 
					
						
							|  |  |  |         expect(inputNativeEl.value).toEqual('oldValue'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         inputEl.triggerEventHandler('compositionstart', null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         inputNativeEl.value = 'updatedValue'; | 
					
						
							|  |  |  |         dispatchEvent(inputNativeEl, 'input'); | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // formControl should update normally
 | 
					
						
							|  |  |  |         expect(fixture.componentInstance.control.value).toEqual('updatedValue'); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-04 01:17:09 +03:00
										 |  |  | function uniqLoginAsyncValidator(expectedValue: string, timeout: number = 0) { | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |   return (c: AbstractControl) => { | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |     let resolve: (result: any) => void; | 
					
						
							|  |  |  |     const promise = new Promise(res => { resolve = res; }); | 
					
						
							|  |  |  |     const res = (c.value == expectedValue) ? null : {'uniqLogin': true}; | 
					
						
							| 
									
										
										
										
											2016-12-04 01:17:09 +03:00
										 |  |  |     setTimeout(() => resolve(res), timeout); | 
					
						
							| 
									
										
										
										
											2016-08-02 15:53:34 -07:00
										 |  |  |     return promise; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-16 10:15:17 -07:00
										 |  |  | function observableValidator(resultArr: number[]): AsyncValidatorFn { | 
					
						
							|  |  |  |   return (c: AbstractControl) => { | 
					
						
							|  |  |  |     return _do.call(timer(100), (resp: any) => resultArr.push(resp)); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | }) | 
					
						
							| 
									
										
										
										
											2017-02-21 03:26:51 +03:00
										 |  |  | class UniqLoginValidator implements AsyncValidator { | 
					
						
							| 
									
										
										
										
											2016-10-19 18:56:31 +02:00
										 |  |  |   @Input('uniq-login-validator') expected: any; | 
					
						
							| 
									
										
										
										
											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) { | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |   return getDOM().classList(el).sort(); | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  | @Component({selector: 'form-control-comp', template: `<input type="text" [formControl]="control">`}) | 
					
						
							| 
									
										
										
										
											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: `
 | 
					
						
							| 
									
										
										
										
											2016-10-11 23:49:36 +01:00
										 |  |  |     <form [formGroup]="form" (ngSubmit)="event=$event"> | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |       <input type="text" formControlName="login"> | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |     </form>`
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | class FormGroupComp { | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |   control: FormControl; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  |   form: FormGroup; | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |   myGroup: FormGroup; | 
					
						
							| 
									
										
										
										
											2016-10-11 23:49:36 +01:00
										 |  |  |   event: Event; | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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"> | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |     </form>`
 | 
					
						
							| 
									
										
										
										
											2016-08-25 14:37:57 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | class NestedFormGroupComp { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | @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> | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |      </div>`
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | 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> | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |      </div>`
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | class FormArrayNestedGroup { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							|  |  |  |   cityArray: FormArray; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'form-group-ng-model', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |   <div [formGroup]="form"> | 
					
						
							|  |  |  |     <input type="text" formControlName="login" [(ngModel)]="login"> | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |    </div>`
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | class FormGroupNgModel { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							|  |  |  |   login: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'form-control-ng-model', | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |   template: `<input type="text" [formControl]="control" [(ngModel)]="login">` | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | 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-10-21 15:14:44 -07:00
										 |  |  |    </div>`
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | 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"> | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |    </div>`
 | 
					
						
							| 
									
										
										
										
											2016-08-06 08:53:41 +02:00
										 |  |  | }) | 
					
						
							|  |  |  | class ValidationBindingsForm { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							|  |  |  |   required: boolean; | 
					
						
							|  |  |  |   minLen: number; | 
					
						
							|  |  |  |   maxLen: number; | 
					
						
							|  |  |  |   pattern: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-10 13:44:04 +03:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'form-control-checkbox-validator', | 
					
						
							|  |  |  |   template: `<input type="checkbox" [formControl]="control">` | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class FormControlCheckboxRequiredValidator { | 
					
						
							|  |  |  |   control: FormControl; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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"> | 
					
						
							| 
									
										
										
										
											2016-10-21 15:14:44 -07:00
										 |  |  |   </div>`
 | 
					
						
							| 
									
										
										
										
											2016-08-17 17:10:56 -07:00
										 |  |  | }) | 
					
						
							|  |  |  | class UniqLoginWrapper { | 
					
						
							|  |  |  |   form: FormGroup; | 
					
						
							| 
									
										
										
										
											2016-06-08 15:36:24 -07:00
										 |  |  | } |