| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  | import {Component, Directive, Input, Type, forwardRef} from '@angular/core'; | 
					
						
							| 
									
										
										
										
											2016-12-14 16:34:19 +00:00
										 |  |  | import {ComponentFixture, TestBed, async, fakeAsync, tick} from '@angular/core/testing'; | 
					
						
							| 
									
										
										
										
											2017-02-21 03:26:51 +03:00
										 |  |  | import {AbstractControl, AsyncValidator, ControlValueAccessor, FormsModule, NG_ASYNC_VALIDATORS, NG_VALUE_ACCESSOR, NgForm} from '@angular/forms'; | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | import {By} from '@angular/platform-browser/src/dom/debug/by'; | 
					
						
							|  |  |  | 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'; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | export function main() { | 
					
						
							|  |  |  |   describe('template-driven forms integration tests', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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]}); | 
					
						
							|  |  |  |       return TestBed.createComponent(component); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |     describe('basic functionality', () => { | 
					
						
							|  |  |  |       it('should support ngModel for standalone fields', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(StandaloneNgModel); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.name = 'oldValue'; | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            // model -> view
 | 
					
						
							|  |  |  |            const input = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							|  |  |  |            expect(input.value).toEqual('oldValue'); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            input.value = 'updatedValue'; | 
					
						
							|  |  |  |            dispatchEvent(input, 'input'); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            // view -> model
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            expect(fixture.componentInstance.name).toEqual('updatedValue'); | 
					
						
							| 
									
										
										
										
											2017-01-12 20:02:45 +08:00
										 |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should ngModel hold ime events until compositionend', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2017-01-30 21:07:09 +03:00
										 |  |  |            const fixture = initTest(StandaloneNgModel); | 
					
						
							| 
									
										
										
										
											2017-01-12 20:02:45 +08:00
										 |  |  |            // model -> view
 | 
					
						
							|  |  |  |            const inputEl = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |            const inputNativeEl = inputEl.nativeElement; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            fixture.componentInstance.name = 'oldValue'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(inputNativeEl.value).toEqual('oldValue'); | 
					
						
							|  |  |  |            // view -> model
 | 
					
						
							|  |  |  |            inputEl.triggerEventHandler('compositionstart', null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            inputNativeEl.value = 'updatedValue'; | 
					
						
							|  |  |  |            dispatchEvent(inputNativeEl, 'input'); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            // should ngModel not update when compositionstart
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(fixture.componentInstance.name).toEqual('oldValue'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            inputEl.triggerEventHandler('compositionend', null); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            // should ngModel update when compositionend
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(fixture.componentInstance.name).toEqual('updatedValue'); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |       it('should support ngModel registration with a parent form', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.name = 'Nancy'; | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            expect(form.value).toEqual({name: 'Nancy'}); | 
					
						
							|  |  |  |            expect(form.valid).toBe(false); | 
					
						
							|  |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-12 22:17:42 +03:00
										 |  |  |       it('should add novalidate by default to form element', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelForm); | 
					
						
							| 
									
										
										
										
											2016-12-12 22:17:42 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const form = fixture.debugElement.query(By.css('form')); | 
					
						
							|  |  |  |            expect(form.nativeElement.getAttribute('novalidate')).toEqual(''); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-21 03:36:48 +03:00
										 |  |  |       it('should be possible to use native validation and angular forms', fakeAsync(() => { | 
					
						
							|  |  |  |            const fixture = initTest(NgModelNativeValidateForm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const form = fixture.debugElement.query(By.css('form')); | 
					
						
							|  |  |  |            expect(form.nativeElement.hasAttribute('novalidate')).toEqual(false); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |       it('should support ngModelGroup', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelGroupForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.first = 'Nancy'; | 
					
						
							|  |  |  |            fixture.componentInstance.last = 'Drew'; | 
					
						
							|  |  |  |            fixture.componentInstance.email = 'some email'; | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            // model -> view
 | 
					
						
							|  |  |  |            const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |            expect(inputs[0].nativeElement.value).toEqual('Nancy'); | 
					
						
							|  |  |  |            expect(inputs[1].nativeElement.value).toEqual('Drew'); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            inputs[0].nativeElement.value = 'Carson'; | 
					
						
							|  |  |  |            dispatchEvent(inputs[0].nativeElement, 'input'); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            // view -> model
 | 
					
						
							|  |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            expect(form.value).toEqual({name: {first: 'Carson', last: 'Drew'}, email: 'some email'}); | 
					
						
							|  |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |       it('should add controls and control groups to form control model', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelGroupForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.first = 'Nancy'; | 
					
						
							|  |  |  |            fixture.componentInstance.last = 'Drew'; | 
					
						
							|  |  |  |            fixture.componentInstance.email = 'some email'; | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            expect(form.control.get('name').value).toEqual({first: 'Nancy', last: 'Drew'}); | 
					
						
							|  |  |  |            expect(form.control.get('name.first').value).toEqual('Nancy'); | 
					
						
							|  |  |  |            expect(form.control.get('email').value).toEqual('some email'); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should remove controls and control groups from form control model', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelNgIfForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.emailShowing = true; | 
					
						
							|  |  |  |            fixture.componentInstance.first = 'Nancy'; | 
					
						
							|  |  |  |            fixture.componentInstance.email = 'some email'; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            expect(form.control.get('email').value).toEqual('some email'); | 
					
						
							|  |  |  |            expect(form.value).toEqual({name: {first: 'Nancy'}, email: 'some email'}); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            // should remove individual control successfully
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.emailShowing = false; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            expect(form.control.get('email')).toBe(null); | 
					
						
							|  |  |  |            expect(form.value).toEqual({name: {first: 'Nancy'}}); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            expect(form.control.get('name').value).toEqual({first: 'Nancy'}); | 
					
						
							|  |  |  |            expect(form.control.get('name.first').value).toEqual('Nancy'); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            // should remove form group successfully
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.groupShowing = false; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            expect(form.control.get('name')).toBe(null); | 
					
						
							|  |  |  |            expect(form.control.get('name.first')).toBe(null); | 
					
						
							|  |  |  |            expect(form.value).toEqual({}); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 23:37:46 +02:00
										 |  |  |       it('should set status classes with ngModel', async(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.name = 'aa'; | 
					
						
							| 
									
										
										
										
											2016-08-25 23:37:46 +02:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            fixture.whenStable().then(() => { | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 23:37:46 +02:00
										 |  |  |              const input = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							|  |  |  |              expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 23:37:46 +02:00
										 |  |  |              dispatchEvent(input, 'blur'); | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 23:37:46 +02:00
										 |  |  |              expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 23:37:46 +02:00
										 |  |  |              input.value = 'updatedValue'; | 
					
						
							|  |  |  |              dispatchEvent(input, 'input'); | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							|  |  |  |              expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']); | 
					
						
							|  |  |  |            }); | 
					
						
							|  |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-19 18:56:31 +02:00
										 |  |  |       it('should set status classes with ngModel and async validators', fakeAsync(() => { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelAsyncValidation, NgAsyncValidator); | 
					
						
							| 
									
										
										
										
											2016-10-19 18:56:31 +02:00
										 |  |  |            fixture.whenStable().then(() => { | 
					
						
							|  |  |  |              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 = 'updatedValue'; | 
					
						
							|  |  |  |              dispatchEvent(input, 'input'); | 
					
						
							|  |  |  |              tick(); | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']); | 
					
						
							|  |  |  |            }); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 23:37:46 +02:00
										 |  |  |       it('should set status classes with ngModelGroup and ngForm', async(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelGroupForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.first = ''; | 
					
						
							| 
									
										
										
										
											2016-08-25 23:37:46 +02:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 23:37:46 +02:00
										 |  |  |            const form = fixture.debugElement.query(By.css('form')).nativeElement; | 
					
						
							|  |  |  |            const modelGroup = fixture.debugElement.query(By.css('[ngModelGroup]')).nativeElement; | 
					
						
							|  |  |  |            const input = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 23:37:46 +02:00
										 |  |  |            // ngModelGroup creates its control asynchronously
 | 
					
						
							|  |  |  |            fixture.whenStable().then(() => { | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							|  |  |  |              expect(sortedClassList(modelGroup)).toEqual([ | 
					
						
							|  |  |  |                'ng-invalid', 'ng-pristine', 'ng-untouched' | 
					
						
							|  |  |  |              ]); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 23:37:46 +02:00
										 |  |  |              expect(sortedClassList(form)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 23:37:46 +02:00
										 |  |  |              dispatchEvent(input, 'blur'); | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 23:37:46 +02:00
										 |  |  |              expect(sortedClassList(modelGroup)).toEqual([ | 
					
						
							|  |  |  |                'ng-invalid', 'ng-pristine', 'ng-touched' | 
					
						
							|  |  |  |              ]); | 
					
						
							|  |  |  |              expect(sortedClassList(form)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 23:37:46 +02:00
										 |  |  |              input.value = 'updatedValue'; | 
					
						
							|  |  |  |              dispatchEvent(input, 'input'); | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 23:37:46 +02:00
										 |  |  |              expect(sortedClassList(modelGroup)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']); | 
					
						
							|  |  |  |              expect(sortedClassList(form)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']); | 
					
						
							|  |  |  |            }); | 
					
						
							|  |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it('should not create a template-driven form when ngNoForm is used', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(NgNoFormComp); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  |         expect(fixture.debugElement.children[0].providerTokens.length).toEqual(0); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-12-12 22:17:42 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it('should not add novalidate when ngNoForm is used', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(NgNoFormComp); | 
					
						
							| 
									
										
										
										
											2016-12-12 22:17:42 +03:00
										 |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  |         const form = fixture.debugElement.query(By.css('form')); | 
					
						
							| 
									
										
										
										
											2017-02-21 03:36:48 +03:00
										 |  |  |         expect(form.nativeElement.hasAttribute('novalidate')).toEqual(false); | 
					
						
							| 
									
										
										
										
											2016-12-12 22:17:42 +03:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |     describe('name and ngModelOptions', () => { | 
					
						
							|  |  |  |       it('should throw if ngModel has a parent form but no name attr or standalone label', () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |         const fixture = initTest(InvalidNgModelNoName); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |         expect(() => fixture.detectChanges()) | 
					
						
							|  |  |  |             .toThrowError(new RegExp(`name attribute must be set`)); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should not throw if ngModel has a parent form, no name attr, and a standalone label', | 
					
						
							|  |  |  |          () => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelOptionsStandalone); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            expect(() => fixture.detectChanges()).not.toThrow(); | 
					
						
							|  |  |  |          }); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |       it('should not register standalone ngModels with parent form', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelOptionsStandalone); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.one = 'some data'; | 
					
						
							|  |  |  |            fixture.componentInstance.two = 'should not show'; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            expect(form.value).toEqual({one: 'some data'}); | 
					
						
							|  |  |  |            expect(inputs[1].nativeElement.value).toEqual('should not show'); | 
					
						
							|  |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |       it('should override name attribute with ngModelOptions name if provided', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.options = {name: 'override'}; | 
					
						
							|  |  |  |            fixture.componentInstance.name = 'some data'; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            expect(form.value).toEqual({override: 'some data'}); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -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', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelForm); | 
					
						
							| 
									
										
										
										
											2016-10-11 23:49:36 +01:00
										 |  |  |            fixture.componentInstance.event = null; | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            const form = fixture.debugElement.query(By.css('form')); | 
					
						
							|  |  |  |            dispatchEvent(form.nativeElement, 'submit'); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-11 23:49:36 +01:00
										 |  |  |            expect(fixture.componentInstance.event.type).toEqual('submit'); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |       it('should mark NgForm as submitted on submit event', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelForm); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            tick(); | 
					
						
							|  |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            expect(form.submitted).toBe(false); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            const formEl = fixture.debugElement.query(By.css('form')).nativeElement; | 
					
						
							|  |  |  |            dispatchEvent(formEl, 'submit'); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            expect(form.submitted).toBe(true); | 
					
						
							|  |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-08-11 23:27:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |       it('should reset the form to empty when reset event is fired', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.name = 'should be cleared'; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-08-11 23:27:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            const formEl = fixture.debugElement.query(By.css('form')); | 
					
						
							|  |  |  |            const input = fixture.debugElement.query(By.css('input')); | 
					
						
							| 
									
										
										
										
											2016-08-11 23:27:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            expect(input.nativeElement.value).toBe('should be cleared');       // view value
 | 
					
						
							|  |  |  |            expect(fixture.componentInstance.name).toBe('should be cleared');  // ngModel value
 | 
					
						
							|  |  |  |            expect(form.value.name).toEqual('should be cleared');              // control value
 | 
					
						
							| 
									
										
										
										
											2016-08-11 23:27:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            dispatchEvent(formEl.nativeElement, 'reset'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-08-11 23:27:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            expect(input.nativeElement.value).toBe('');         // view value
 | 
					
						
							|  |  |  |            expect(fixture.componentInstance.name).toBe(null);  // ngModel value
 | 
					
						
							|  |  |  |            expect(form.value.name).toEqual(null);              // control value
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |       it('should reset the form submit state when reset button is clicked', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelForm); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            const formEl = fixture.debugElement.query(By.css('form')); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            dispatchEvent(formEl.nativeElement, 'submit'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            expect(form.submitted).toBe(true); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            dispatchEvent(formEl.nativeElement, 'reset'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            expect(form.submitted).toBe(false); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |     describe('valueChange and statusChange events', () => { | 
					
						
							|  |  |  |       it('should emit valueChanges and statusChanges on init', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelForm); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.name = 'aa'; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            expect(form.valid).toEqual(true); | 
					
						
							|  |  |  |            expect(form.value).toEqual({}); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            let formValidity: string; | 
					
						
							|  |  |  |            let formValue: Object; | 
					
						
							| 
									
										
										
										
											2016-08-02 15:53:34 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            form.statusChanges.subscribe((status: string) => formValidity = status); | 
					
						
							|  |  |  |            form.valueChanges.subscribe((value: string) => formValue = value); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            expect(formValidity).toEqual('INVALID'); | 
					
						
							|  |  |  |            expect(formValue).toEqual({name: 'aa'}); | 
					
						
							|  |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |       it('should mark controls dirty before emitting the value change event', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelForm); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm).form; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            form.get('name').valueChanges.subscribe( | 
					
						
							|  |  |  |                () => { expect(form.get('name').dirty).toBe(true); }); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            const inputEl = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							|  |  |  |            inputEl.value = 'newValue'; | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            dispatchEvent(inputEl, 'input'); | 
					
						
							|  |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |       it('should mark controls pristine before emitting the value change event when resetting ', | 
					
						
							|  |  |  |          fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelForm); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm).form; | 
					
						
							|  |  |  |            const formEl = fixture.debugElement.query(By.css('form')).nativeElement; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            const inputEl = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            inputEl.value = 'newValue'; | 
					
						
							|  |  |  |            dispatchEvent(inputEl, 'input'); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            expect(form.get('name').pristine).toBe(false); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            form.get('name').valueChanges.subscribe( | 
					
						
							|  |  |  |                () => { expect(form.get('name').pristine).toBe(true); }); | 
					
						
							| 
									
										
										
										
											2016-07-28 14:25:33 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |            dispatchEvent(formEl, 'reset'); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |          })); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |     describe('disabled controls', () => { | 
					
						
							|  |  |  |       it('should not consider disabled controls in value or validation', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelGroupForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.isDisabled = false; | 
					
						
							|  |  |  |            fixture.componentInstance.first = ''; | 
					
						
							|  |  |  |            fixture.componentInstance.last = 'Drew'; | 
					
						
							|  |  |  |            fixture.componentInstance.email = 'some email'; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            expect(form.value).toEqual({name: {first: '', last: 'Drew'}, email: 'some email'}); | 
					
						
							|  |  |  |            expect(form.valid).toBe(false); | 
					
						
							|  |  |  |            expect(form.control.get('name.first').disabled).toBe(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            fixture.componentInstance.isDisabled = true; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(form.value).toEqual({name: {last: 'Drew'}, email: 'some email'}); | 
					
						
							|  |  |  |            expect(form.valid).toBe(true); | 
					
						
							|  |  |  |            expect(form.control.get('name.first').disabled).toBe(true); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should add disabled attribute in the UI if disable() is called programmatically', | 
					
						
							|  |  |  |          fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelGroupForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.isDisabled = false; | 
					
						
							|  |  |  |            fixture.componentInstance.first = 'Nancy'; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            form.control.get('name.first').disable(); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const input = fixture.debugElement.query(By.css(`[name="first"]`)); | 
					
						
							|  |  |  |            expect(input.nativeElement.disabled).toBe(true); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should disable a custom control if disabled attr is added', async(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelCustomWrapper, NgModelCustomComp); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.name = 'Nancy'; | 
					
						
							|  |  |  |            fixture.componentInstance.isDisabled = true; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            fixture.whenStable().then(() => { | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							|  |  |  |              fixture.whenStable().then(() => { | 
					
						
							|  |  |  |                const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |                expect(form.control.get('name').disabled).toBe(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                const customInput = fixture.debugElement.query(By.css('[name="custom"]')); | 
					
						
							|  |  |  |                expect(customInput.nativeElement.disabled).toEqual(true); | 
					
						
							|  |  |  |              }); | 
					
						
							|  |  |  |            }); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 14:55:47 -07:00
										 |  |  |       it('should disable a control with unbound disabled attr', fakeAsync(() => { | 
					
						
							|  |  |  |            TestBed.overrideComponent(NgModelForm, { | 
					
						
							|  |  |  |              set: { | 
					
						
							|  |  |  |                template: `
 | 
					
						
							|  |  |  |             <form> | 
					
						
							|  |  |  |              <input name="name" [(ngModel)]="name" disabled> | 
					
						
							|  |  |  |             </form> | 
					
						
							|  |  |  |           `,
 | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  |            }); | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelForm); | 
					
						
							| 
									
										
										
										
											2016-09-20 14:55:47 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            expect(form.control.get('name').disabled).toBe(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |            expect(input.nativeElement.disabled).toEqual(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            form.control.enable(); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            expect(input.nativeElement.disabled).toEqual(false); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 09:08:12 -07:00
										 |  |  |       it('should disable radio controls properly with programmatic call', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelRadioForm); | 
					
						
							| 
									
										
										
										
											2016-09-20 09:08:12 -07:00
										 |  |  |            fixture.componentInstance.food = 'fish'; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            form.control.get('food').disable(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |            expect(inputs[0].nativeElement.disabled).toBe(true); | 
					
						
							|  |  |  |            expect(inputs[1].nativeElement.disabled).toBe(true); | 
					
						
							|  |  |  |            expect(inputs[2].nativeElement.disabled).toBe(false); | 
					
						
							|  |  |  |            expect(inputs[3].nativeElement.disabled).toBe(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            form.control.disable(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(inputs[0].nativeElement.disabled).toBe(true); | 
					
						
							|  |  |  |            expect(inputs[1].nativeElement.disabled).toBe(true); | 
					
						
							|  |  |  |            expect(inputs[2].nativeElement.disabled).toBe(true); | 
					
						
							|  |  |  |            expect(inputs[3].nativeElement.disabled).toBe(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            form.control.enable(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(inputs[0].nativeElement.disabled).toBe(false); | 
					
						
							|  |  |  |            expect(inputs[1].nativeElement.disabled).toBe(false); | 
					
						
							|  |  |  |            expect(inputs[2].nativeElement.disabled).toBe(false); | 
					
						
							|  |  |  |            expect(inputs[3].nativeElement.disabled).toBe(false); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-19 20:12:13 +03:00
										 |  |  |     describe('range control', () => { | 
					
						
							|  |  |  |       it('should support <type=range>', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelRangeForm); | 
					
						
							| 
									
										
										
										
											2016-10-19 20:12:13 +03:00
										 |  |  |            // model -> view
 | 
					
						
							|  |  |  |            fixture.componentInstance.val = 4; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |            const input = fixture.debugElement.query(By.css('input')); | 
					
						
							| 
									
										
										
										
											2016-10-19 20:12:13 +03:00
										 |  |  |            expect(input.nativeElement.value).toBe('4'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-11-12 14:08:58 +01:00
										 |  |  |            const newVal = '4'; | 
					
						
							| 
									
										
										
										
											2016-10-19 20:12:13 +03:00
										 |  |  |            input.triggerEventHandler('input', {target: {value: newVal}}); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            // view -> model
 | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            expect(typeof(fixture.componentInstance.val)).toBe('number'); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |     describe('radio controls', () => { | 
					
						
							|  |  |  |       it('should support <type=radio>', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelRadioForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.food = 'fish'; | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            // model -> view
 | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  |            const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |            expect(inputs[0].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |            expect(inputs[1].nativeElement.checked).toEqual(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            dispatchEvent(inputs[0].nativeElement, 'change'); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            // view -> model
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            expect(fixture.componentInstance.food).toEqual('chicken'); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  |            expect(inputs[1].nativeElement.checked).toEqual(false); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |       it('should support multiple named <type=radio> groups', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelRadioForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.food = 'fish'; | 
					
						
							|  |  |  |            fixture.componentInstance.drink = 'sprite'; | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |            expect(inputs[0].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |            expect(inputs[1].nativeElement.checked).toEqual(true); | 
					
						
							|  |  |  |            expect(inputs[2].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |            expect(inputs[3].nativeElement.checked).toEqual(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            dispatchEvent(inputs[0].nativeElement, 'change'); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            expect(fixture.componentInstance.food).toEqual('chicken'); | 
					
						
							|  |  |  |            expect(fixture.componentInstance.drink).toEqual('sprite'); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  |            expect(inputs[1].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |            expect(inputs[2].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |            expect(inputs[3].nativeElement.checked).toEqual(true); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-09-12 15:15:58 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it('should support initial undefined value', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelRadioForm); | 
					
						
							| 
									
										
										
										
											2016-09-12 15:15:58 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |            expect(inputs[0].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |            expect(inputs[1].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |            expect(inputs[2].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |            expect(inputs[3].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should support resetting properly', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelRadioForm); | 
					
						
							| 
									
										
										
										
											2016-09-12 15:15:58 -07:00
										 |  |  |            fixture.componentInstance.food = 'chicken'; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const form = fixture.debugElement.query(By.css('form')); | 
					
						
							|  |  |  |            dispatchEvent(form.nativeElement, 'reset'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |            expect(inputs[0].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |            expect(inputs[1].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should support setting value to null and undefined', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelRadioForm); | 
					
						
							| 
									
										
										
										
											2016-09-12 15:15:58 -07:00
										 |  |  |            fixture.componentInstance.food = 'chicken'; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            fixture.componentInstance.food = null; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const inputs = fixture.debugElement.queryAll(By.css('input')); | 
					
						
							|  |  |  |            expect(inputs[0].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |            expect(inputs[1].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            fixture.componentInstance.food = 'chicken'; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            fixture.componentInstance.food = undefined; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            expect(inputs[0].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |            expect(inputs[1].nativeElement.checked).toEqual(false); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |     describe('select controls', () => { | 
					
						
							|  |  |  |       it('with option values that are objects', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelSelectForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            const comp = fixture.componentInstance; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            comp.cities = [{'name': 'SF'}, {'name': 'NYC'}, {'name': 'Buffalo'}]; | 
					
						
							|  |  |  |            comp.selectedCity = comp.cities[1]; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const select = fixture.debugElement.query(By.css('select')); | 
					
						
							|  |  |  |            const nycOption = fixture.debugElement.queryAll(By.css('option'))[1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            // model -> view
 | 
					
						
							|  |  |  |            expect(select.nativeElement.value).toEqual('1: Object'); | 
					
						
							|  |  |  |            expect(nycOption.nativeElement.selected).toBe(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            select.nativeElement.value = '2: Object'; | 
					
						
							|  |  |  |            dispatchEvent(select.nativeElement, 'change'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            // view -> model
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            expect(comp.selectedCity['name']).toEqual('Buffalo'); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('when new options are added', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelSelectForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            const comp = fixture.componentInstance; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            comp.cities = [{'name': 'SF'}, {'name': 'NYC'}]; | 
					
						
							|  |  |  |            comp.selectedCity = comp.cities[1]; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            comp.cities.push({'name': 'Buffalo'}); | 
					
						
							|  |  |  |            comp.selectedCity = comp.cities[2]; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const select = fixture.debugElement.query(By.css('select')); | 
					
						
							|  |  |  |            const buffalo = fixture.debugElement.queryAll(By.css('option'))[2]; | 
					
						
							|  |  |  |            expect(select.nativeElement.value).toEqual('2: Object'); | 
					
						
							|  |  |  |            expect(buffalo.nativeElement.selected).toBe(true); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('when options are removed', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelSelectForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            const comp = fixture.componentInstance; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            comp.cities = [{'name': 'SF'}, {'name': 'NYC'}]; | 
					
						
							|  |  |  |            comp.selectedCity = comp.cities[1]; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const select = fixture.debugElement.query(By.css('select')); | 
					
						
							|  |  |  |            expect(select.nativeElement.value).toEqual('1: Object'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            comp.cities.pop(); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(select.nativeElement.value).not.toEqual('1: Object'); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('when option values have same content, but different identities', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelSelectForm); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            const comp = fixture.componentInstance; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            comp.cities = [{'name': 'SF'}, {'name': 'NYC'}, {'name': 'NYC'}]; | 
					
						
							|  |  |  |            comp.selectedCity = comp.cities[0]; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            comp.selectedCity = comp.cities[2]; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const select = fixture.debugElement.query(By.css('select')); | 
					
						
							|  |  |  |            const secondNYC = fixture.debugElement.queryAll(By.css('option'))[2]; | 
					
						
							|  |  |  |            expect(select.nativeElement.value).toEqual('2: Object'); | 
					
						
							|  |  |  |            expect(secondNYC.nativeElement.selected).toBe(true); | 
					
						
							|  |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-11-12 02:58:43 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it('should work with null option', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelSelectWithNullForm); | 
					
						
							| 
									
										
										
										
											2016-11-12 02:58:43 +03:00
										 |  |  |            const comp = fixture.componentInstance; | 
					
						
							|  |  |  |            comp.cities = [{'name': 'SF'}, {'name': 'NYC'}]; | 
					
						
							|  |  |  |            comp.selectedCity = null; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const select = fixture.debugElement.query(By.css('select')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            select.nativeElement.value = '2: Object'; | 
					
						
							|  |  |  |            dispatchEvent(select.nativeElement, 'change'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            expect(comp.selectedCity['name']).toEqual('NYC'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            select.nativeElement.value = '0: null'; | 
					
						
							|  |  |  |            dispatchEvent(select.nativeElement, 'change'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            expect(comp.selectedCity).toEqual(null); | 
					
						
							|  |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-12-14 16:34:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-10 00:10:40 +03:00
										 |  |  |       it('should throw an error when compareWith is not a function', () => { | 
					
						
							|  |  |  |         const fixture = initTest(NgModelSelectWithCustomCompareFnForm); | 
					
						
							|  |  |  |         const comp = fixture.componentInstance; | 
					
						
							|  |  |  |         comp.compareFn = null; | 
					
						
							|  |  |  |         expect(() => fixture.detectChanges()) | 
					
						
							|  |  |  |             .toThrowError(/compareWith must be a function, but received null/); | 
					
						
							| 
									
										
										
										
											2016-12-14 16:34:19 +00:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-10 00:10:40 +03:00
										 |  |  |       it('should compare options using provided compareWith function', fakeAsync(() => { | 
					
						
							|  |  |  |            const fixture = initTest(NgModelSelectWithCustomCompareFnForm); | 
					
						
							|  |  |  |            const comp = fixture.componentInstance; | 
					
						
							|  |  |  |            comp.selectedCity = {id: 1, name: 'SF'}; | 
					
						
							|  |  |  |            comp.cities = [{id: 1, name: 'SF'}, {id: 2, name: 'LA'}]; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-12-14 16:34:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-10 00:10:40 +03:00
										 |  |  |            const select = fixture.debugElement.query(By.css('select')); | 
					
						
							|  |  |  |            const sfOption = fixture.debugElement.query(By.css('option')); | 
					
						
							|  |  |  |            expect(select.nativeElement.value).toEqual('0: Object'); | 
					
						
							|  |  |  |            expect(sfOption.nativeElement.selected).toBe(true); | 
					
						
							| 
									
										
										
										
											2016-12-14 16:34:19 +00:00
										 |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-12-10 00:10:40 +03:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-12-14 16:34:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-10 00:10:40 +03:00
										 |  |  |     describe('select multiple controls', () => { | 
					
						
							|  |  |  |       describe('select options', () => { | 
					
						
							|  |  |  |         let fixture: ComponentFixture<NgModelSelectMultipleForm>; | 
					
						
							|  |  |  |         let comp: NgModelSelectMultipleForm; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         beforeEach(() => { | 
					
						
							|  |  |  |           fixture = initTest(NgModelSelectMultipleForm); | 
					
						
							|  |  |  |           comp = fixture.componentInstance; | 
					
						
							|  |  |  |           comp.cities = [{'name': 'SF'}, {'name': 'NYC'}, {'name': 'Buffalo'}]; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const detectChangesAndTick = (): void => { | 
					
						
							|  |  |  |           fixture.detectChanges(); | 
					
						
							|  |  |  |           tick(); | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const setSelectedCities = (selectedCities: any): void => { | 
					
						
							|  |  |  |           comp.selectedCities = selectedCities; | 
					
						
							|  |  |  |           detectChangesAndTick(); | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const selectOptionViaUI = (valueString: string): void => { | 
					
						
							|  |  |  |           const select = fixture.debugElement.query(By.css('select')); | 
					
						
							|  |  |  |           select.nativeElement.value = valueString; | 
					
						
							|  |  |  |           dispatchEvent(select.nativeElement, 'change'); | 
					
						
							|  |  |  |           detectChangesAndTick(); | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const assertOptionElementSelectedState = (selectedStates: boolean[]): void => { | 
					
						
							|  |  |  |           const options = fixture.debugElement.queryAll(By.css('option')); | 
					
						
							|  |  |  |           if (options.length !== selectedStates.length) { | 
					
						
							|  |  |  |             throw 'the selected state values to assert does not match the number of options'; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           for (let i = 0; i < selectedStates.length; i++) { | 
					
						
							|  |  |  |             expect(options[i].nativeElement.selected).toBe(selectedStates[i]); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should reflect state of model after option selected and new options subsequently added', | 
					
						
							|  |  |  |            fakeAsync(() => { | 
					
						
							|  |  |  |              setSelectedCities([]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              selectOptionViaUI('1: Object'); | 
					
						
							|  |  |  |              assertOptionElementSelectedState([false, true, false]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              comp.cities.push({'name': 'Chicago'}); | 
					
						
							|  |  |  |              detectChangesAndTick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              assertOptionElementSelectedState([false, true, false, false]); | 
					
						
							|  |  |  |            })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('should reflect state of model after option selected and then other options removed', | 
					
						
							|  |  |  |            fakeAsync(() => { | 
					
						
							|  |  |  |              setSelectedCities([]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              selectOptionViaUI('1: Object'); | 
					
						
							|  |  |  |              assertOptionElementSelectedState([false, true, false]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              comp.cities.pop(); | 
					
						
							|  |  |  |              detectChangesAndTick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              assertOptionElementSelectedState([false, true]); | 
					
						
							|  |  |  |            })); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-12-14 16:34:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-10 00:10:40 +03:00
										 |  |  |       it('should throw an error when compareWith is not a function', () => { | 
					
						
							|  |  |  |         const fixture = initTest(NgModelSelectMultipleWithCustomCompareFnForm); | 
					
						
							|  |  |  |         const comp = fixture.componentInstance; | 
					
						
							|  |  |  |         comp.compareFn = null; | 
					
						
							|  |  |  |         expect(() => fixture.detectChanges()) | 
					
						
							|  |  |  |             .toThrowError(/compareWith must be a function, but received null/); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-11-01 22:43:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-10 00:10:40 +03:00
										 |  |  |       it('should compare options using provided compareWith function', fakeAsync(() => { | 
					
						
							|  |  |  |            const fixture = initTest(NgModelSelectMultipleWithCustomCompareFnForm); | 
					
						
							|  |  |  |            const comp = fixture.componentInstance; | 
					
						
							|  |  |  |            comp.cities = [{id: 1, name: 'SF'}, {id: 2, name: 'LA'}]; | 
					
						
							|  |  |  |            comp.selectedCities = [comp.cities[0]]; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-11-01 22:43:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-10 00:10:40 +03:00
										 |  |  |            const select = fixture.debugElement.query(By.css('select')); | 
					
						
							|  |  |  |            const sfOption = fixture.debugElement.query(By.css('option')); | 
					
						
							|  |  |  |            expect(select.nativeElement.value).toEqual('0: Object'); | 
					
						
							|  |  |  |            expect(sfOption.nativeElement.selected).toBe(true); | 
					
						
							| 
									
										
										
										
											2016-12-14 16:34:19 +00:00
										 |  |  |          })); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |     describe('custom value accessors', () => { | 
					
						
							|  |  |  |       it('should support standard writing to view and model', async(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelCustomWrapper, NgModelCustomComp); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.name = 'Nancy'; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            fixture.whenStable().then(() => { | 
					
						
							|  |  |  |              fixture.detectChanges(); | 
					
						
							|  |  |  |              fixture.whenStable().then(() => { | 
					
						
							|  |  |  |                // model -> view
 | 
					
						
							|  |  |  |                const customInput = fixture.debugElement.query(By.css('[name="custom"]')); | 
					
						
							|  |  |  |                expect(customInput.nativeElement.value).toEqual('Nancy'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                customInput.nativeElement.value = 'Carson'; | 
					
						
							|  |  |  |                dispatchEvent(customInput.nativeElement, 'input'); | 
					
						
							|  |  |  |                fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                // view -> model
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |                expect(fixture.componentInstance.name).toEqual('Carson'); | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |              }); | 
					
						
							|  |  |  |            }); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |     describe('validation directives', () => { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-10 13:44:04 +03:00
										 |  |  |       it('required validator should validate checkbox', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelCheckboxRequiredValidator); | 
					
						
							| 
									
										
										
										
											2016-12-10 13:44:04 +03:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const control = | 
					
						
							|  |  |  |                fixture.debugElement.children[0].injector.get(NgForm).control.get('checkbox'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |            expect(input.nativeElement.checked).toBe(false); | 
					
						
							|  |  |  |            expect(control.hasError('required')).toBe(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            fixture.componentInstance.required = true; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(input.nativeElement.checked).toBe(false); | 
					
						
							|  |  |  |            expect(control.hasError('required')).toBe(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.nativeElement.checked = true; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'change'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(input.nativeElement.checked).toBe(true); | 
					
						
							|  |  |  |            expect(control.hasError('required')).toBe(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.nativeElement.checked = false; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'change'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(input.nativeElement.checked).toBe(false); | 
					
						
							|  |  |  |            expect(control.hasError('required')).toBe(true); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-29 20:07:02 +03:00
										 |  |  |       it('should validate email', fakeAsync(() => { | 
					
						
							|  |  |  |            const fixture = initTest(NgModelEmailValidator); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const control = | 
					
						
							|  |  |  |                fixture.debugElement.children[0].injector.get(NgForm).control.get('email'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  |            expect(control.hasError('email')).toBe(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            fixture.componentInstance.validatorEnabled = true; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(input.nativeElement.value).toEqual(''); | 
					
						
							|  |  |  |            expect(control.hasError('email')).toBe(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.nativeElement.value = 'test@gmail.com'; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(input.nativeElement.value).toEqual('test@gmail.com'); | 
					
						
							|  |  |  |            expect(control.hasError('email')).toBe(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.nativeElement.value = 'text'; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(input.nativeElement.value).toEqual('text'); | 
					
						
							|  |  |  |            expect(control.hasError('email')).toBe(true); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |       it('should support dir validators using bindings', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelValidationBindings); | 
					
						
							| 
									
										
										
										
											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-29 11:33:49 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            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'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            expect(form.control.hasError('required', ['required'])).toEqual(true); | 
					
						
							|  |  |  |            expect(form.control.hasError('minlength', ['minlength'])).toEqual(true); | 
					
						
							|  |  |  |            expect(form.control.hasError('maxlength', ['maxlength'])).toEqual(true); | 
					
						
							|  |  |  |            expect(form.control.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-11-16 05:48:34 +03:00
										 |  |  |       it('should support optional fields with string pattern validator', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelMultipleValidators); | 
					
						
							| 
									
										
										
										
											2016-10-10 18:17:45 +02:00
										 |  |  |            fixture.componentInstance.required = false; | 
					
						
							|  |  |  |            fixture.componentInstance.pattern = '[a-z]+'; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.nativeElement.value = ''; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            expect(form.valid).toBeTruthy(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.nativeElement.value = '1'; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            expect(form.valid).toBeFalsy(); | 
					
						
							|  |  |  |            expect(form.control.hasError('pattern', ['tovalidate'])).toBeTruthy(); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-16 05:48:34 +03:00
										 |  |  |       it('should support optional fields with RegExp pattern validator', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelMultipleValidators); | 
					
						
							| 
									
										
										
										
											2016-11-16 05:48:34 +03:00
										 |  |  |            fixture.componentInstance.required = false; | 
					
						
							|  |  |  |            fixture.componentInstance.pattern = /^[a-z]+$/; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.nativeElement.value = ''; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            expect(form.valid).toBeTruthy(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.nativeElement.value = '1'; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            expect(form.valid).toBeFalsy(); | 
					
						
							|  |  |  |            expect(form.control.hasError('pattern', ['tovalidate'])).toBeTruthy(); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-10 18:17:45 +02:00
										 |  |  |       it('should support optional fields with minlength validator', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelMultipleValidators); | 
					
						
							| 
									
										
										
										
											2016-10-10 18:17:45 +02:00
										 |  |  |            fixture.componentInstance.required = false; | 
					
						
							|  |  |  |            fixture.componentInstance.minLen = 2; | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            const input = fixture.debugElement.query(By.css('input')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.nativeElement.value = ''; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            expect(form.valid).toBeTruthy(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            input.nativeElement.value = '1'; | 
					
						
							|  |  |  |            dispatchEvent(input.nativeElement, 'input'); | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            expect(form.valid).toBeFalsy(); | 
					
						
							|  |  |  |            expect(form.control.hasError('minlength', ['tovalidate'])).toBeTruthy(); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |       it('changes on bound properties should change the validation state of the form', | 
					
						
							|  |  |  |          fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelValidationBindings); | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            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'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            const form = fixture.debugElement.children[0].injector.get(NgForm); | 
					
						
							|  |  |  |            expect(form.control.hasError('required', ['required'])).toEqual(false); | 
					
						
							|  |  |  |            expect(form.control.hasError('minlength', ['minlength'])).toEqual(false); | 
					
						
							|  |  |  |            expect(form.control.hasError('maxlength', ['maxlength'])).toEqual(false); | 
					
						
							|  |  |  |            expect(form.control.hasError('pattern', ['pattern'])).toEqual(false); | 
					
						
							|  |  |  |            expect(form.valid).toEqual(true); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-29 11:33:49 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            dispatchEvent(required.nativeElement, 'input'); | 
					
						
							|  |  |  |            dispatchEvent(minLength.nativeElement, 'input'); | 
					
						
							|  |  |  |            dispatchEvent(maxLength.nativeElement, 'input'); | 
					
						
							|  |  |  |            dispatchEvent(pattern.nativeElement, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(form.control.hasError('required', ['required'])).toEqual(true); | 
					
						
							|  |  |  |            expect(form.control.hasError('minlength', ['minlength'])).toEqual(true); | 
					
						
							|  |  |  |            expect(form.control.hasError('maxlength', ['maxlength'])).toEqual(true); | 
					
						
							|  |  |  |            expect(form.control.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-29 11:33:49 -07:00
										 |  |  |                .toEqual(minLength.nativeElement.getAttribute('minlength')); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            expect(fixture.componentInstance.maxLen.toString()) | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |                .toEqual(maxLength.nativeElement.getAttribute('maxlength')); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            expect(fixture.componentInstance.pattern.toString()) | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |                .toEqual(pattern.nativeElement.getAttribute('pattern')); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.required = false; | 
					
						
							|  |  |  |            fixture.componentInstance.minLen = null; | 
					
						
							|  |  |  |            fixture.componentInstance.maxLen = null; | 
					
						
							|  |  |  |            fixture.componentInstance.pattern = null; | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            expect(form.control.hasError('required', ['required'])).toEqual(false); | 
					
						
							|  |  |  |            expect(form.control.hasError('minlength', ['minlength'])).toEqual(false); | 
					
						
							|  |  |  |            expect(form.control.hasError('maxlength', ['maxlength'])).toEqual(false); | 
					
						
							|  |  |  |            expect(form.control.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-07-25 15:57:51 -07:00
										 |  |  |     describe('ngModel corner cases', () => { | 
					
						
							|  |  |  |       it('should update the view when the model is set back to what used to be in the view', | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |          fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(StandaloneNgModel); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.name = ''; | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            const input = fixture.debugElement.query(By.css('input')).nativeElement; | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  |            input.value = 'aa'; | 
					
						
							|  |  |  |            input.selectionStart = 1; | 
					
						
							|  |  |  |            dispatchEvent(input, 'input'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            expect(fixture.componentInstance.name).toEqual('aa'); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |            // Programmatically update the input value to be "bb".
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.name = 'bb'; | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            expect(input.value).toEqual('bb'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            // Programatically set it back to "aa".
 | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |            fixture.componentInstance.name = 'aa'; | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  |            fixture.detectChanges(); | 
					
						
							|  |  |  |            tick(); | 
					
						
							|  |  |  |            expect(input.value).toEqual('aa'); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |       it('should not crash when validity is checked from a binding', fakeAsync(() => { | 
					
						
							| 
									
										
										
										
											2016-12-16 02:07:26 +01:00
										 |  |  |            const fixture = initTest(NgModelValidBinding); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  |            tick(); | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |            expect(() => fixture.detectChanges()).not.toThrowError(); | 
					
						
							|  |  |  |          })); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-10-19 18:56:31 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'standalone-ng-model', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <input type="text" [(ngModel)]="name"> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class StandaloneNgModel { | 
					
						
							|  |  |  |   name: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-form', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							| 
									
										
										
										
											2016-10-11 23:49:36 +01:00
										 |  |  |     <form (ngSubmit)="event=$event" (reset)="onReset()"> | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |       <input name="name" [(ngModel)]="name" minlength="10" [ngModelOptions]="options"> | 
					
						
							|  |  |  |     </form> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelForm { | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  |   name: string; | 
					
						
							| 
									
										
										
										
											2016-10-11 23:49:36 +01:00
										 |  |  |   event: Event; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |   options = {}; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   onReset() {} | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-21 03:36:48 +03:00
										 |  |  | @Component({selector: 'ng-model-native-validate-form', template: `<form ngNativeValidate></form>`}) | 
					
						
							|  |  |  | class NgModelNativeValidateForm { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-group-form', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <form> | 
					
						
							|  |  |  |       <div ngModelGroup="name"> | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |         <input name="first" [(ngModel)]="first" required [disabled]="isDisabled"> | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |         <input name="last" [(ngModel)]="last"> | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |       <input name="email" [(ngModel)]="email"> | 
					
						
							|  |  |  |     </form> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelGroupForm { | 
					
						
							|  |  |  |   first: string; | 
					
						
							|  |  |  |   last: string; | 
					
						
							|  |  |  |   email: string; | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |   isDisabled: boolean; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  |   selector: 'ng-model-valid-binding', | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |   template: `
 | 
					
						
							|  |  |  |     <form> | 
					
						
							|  |  |  |       <div ngModelGroup="name" #group="ngModelGroup"> | 
					
						
							|  |  |  |         <input name="first" [(ngModel)]="first" required> | 
					
						
							|  |  |  |         {{ group.valid }} | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |     </form> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelValidBinding { | 
					
						
							|  |  |  |   first: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-ngif-form', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <form> | 
					
						
							|  |  |  |       <div ngModelGroup="name" *ngIf="groupShowing"> | 
					
						
							|  |  |  |         <input name="first" [(ngModel)]="first"> | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |       <input name="email" [(ngModel)]="email" *ngIf="emailShowing"> | 
					
						
							|  |  |  |     </form> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelNgIfForm { | 
					
						
							|  |  |  |   first: string; | 
					
						
							|  |  |  |   groupShowing = true; | 
					
						
							|  |  |  |   emailShowing = true; | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |   email: string; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-no-form', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <form ngNoForm> | 
					
						
							|  |  |  |       <input name="name"> | 
					
						
							|  |  |  |     </form> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgNoFormComp { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'invalid-ng-model-noname', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <form> | 
					
						
							|  |  |  |       <input [(ngModel)]="name"> | 
					
						
							|  |  |  |     </form> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class InvalidNgModelNoName { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-options-standalone', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <form> | 
					
						
							|  |  |  |       <input name="one" [(ngModel)]="one"> | 
					
						
							|  |  |  |       <input [(ngModel)]="two" [ngModelOptions]="{standalone: true}"> | 
					
						
							|  |  |  |     </form> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelOptionsStandalone { | 
					
						
							|  |  |  |   one: string; | 
					
						
							|  |  |  |   two: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-19 20:12:13 +03:00
										 |  |  | @Component({selector: 'ng-model-range-form', template: '<input type="range" [(ngModel)]="val">'}) | 
					
						
							|  |  |  | class NgModelRangeForm { | 
					
						
							|  |  |  |   val: any; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-radio-form', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <form> | 
					
						
							|  |  |  |       <input type="radio" name="food" [(ngModel)]="food" value="chicken"> | 
					
						
							|  |  |  |       <input type="radio" name="food"  [(ngModel)]="food" value="fish"> | 
					
						
							| 
									
										
										
										
											2016-09-20 09:08:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |       <input type="radio" name="drink" [(ngModel)]="drink" value="cola"> | 
					
						
							|  |  |  |       <input type="radio" name="drink" [(ngModel)]="drink" value="sprite"> | 
					
						
							|  |  |  |     </form> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelRadioForm { | 
					
						
							|  |  |  |   food: string; | 
					
						
							|  |  |  |   drink: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-select-form', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <select [(ngModel)]="selectedCity"> | 
					
						
							|  |  |  |       <option *ngFor="let c of cities" [ngValue]="c"> {{c.name}} </option> | 
					
						
							|  |  |  |     </select> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelSelectForm { | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |   selectedCity: {[k: string]: string} = {}; | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  |   cities: any[] = []; | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-12 02:58:43 +03:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-select-null-form', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <select [(ngModel)]="selectedCity"> | 
					
						
							|  |  |  |       <option *ngFor="let c of cities" [ngValue]="c"> {{c.name}} </option> | 
					
						
							|  |  |  |       <option [ngValue]="null">Unspecified</option> | 
					
						
							|  |  |  |     </select> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelSelectWithNullForm { | 
					
						
							|  |  |  |   selectedCity: {[k: string]: string} = {}; | 
					
						
							|  |  |  |   cities: any[] = []; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-10 00:10:40 +03:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-select-compare-with', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <select [(ngModel)]="selectedCity" [compareWith]="compareFn"> | 
					
						
							|  |  |  |       <option *ngFor="let c of cities" [ngValue]="c"> {{c.name}} </option> | 
					
						
							|  |  |  |     </select> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelSelectWithCustomCompareFnForm { | 
					
						
							| 
									
										
										
										
											2017-01-31 19:01:48 -06:00
										 |  |  |   compareFn: | 
					
						
							|  |  |  |       (o1: any, o2: any) => boolean = (o1: any, o2: any) => o1 && o2? o1.id === o2.id: o1 === o2; | 
					
						
							| 
									
										
										
										
											2016-12-10 00:10:40 +03:00
										 |  |  |   selectedCity: any = {}; | 
					
						
							|  |  |  |   cities: any[] = []; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-select-multiple-compare-with', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <select multiple [(ngModel)]="selectedCities" [compareWith]="compareFn"> | 
					
						
							|  |  |  |       <option *ngFor="let c of cities" [ngValue]="c"> {{c.name}} </option> | 
					
						
							|  |  |  |     </select> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelSelectMultipleWithCustomCompareFnForm { | 
					
						
							| 
									
										
										
										
											2017-01-31 19:01:48 -06:00
										 |  |  |   compareFn: | 
					
						
							|  |  |  |       (o1: any, o2: any) => boolean = (o1: any, o2: any) => o1 && o2? o1.id === o2.id: o1 === o2; | 
					
						
							| 
									
										
										
										
											2016-12-10 00:10:40 +03:00
										 |  |  |   selectedCities: any[] = []; | 
					
						
							|  |  |  |   cities: any[] = []; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-14 16:34:19 +00:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-select-multiple-form', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <select multiple [(ngModel)]="selectedCities"> | 
					
						
							|  |  |  |       <option *ngFor="let c of cities" [ngValue]="c"> {{c.name}} </option> | 
					
						
							|  |  |  |     </select> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelSelectMultipleForm { | 
					
						
							|  |  |  |   selectedCities: any[]; | 
					
						
							|  |  |  |   cities: any[] = []; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-24 16:58:43 -07:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-custom-comp', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <input name="custom" [(ngModel)]="model" (ngModelChange)="changeFn($event)" [disabled]="isDisabled"> | 
					
						
							|  |  |  |   `,
 | 
					
						
							|  |  |  |   providers: [{provide: NG_VALUE_ACCESSOR, multi: true, useExisting: NgModelCustomComp}] | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelCustomComp implements ControlValueAccessor { | 
					
						
							|  |  |  |   model: string; | 
					
						
							|  |  |  |   @Input('disabled') isDisabled: boolean = false; | 
					
						
							|  |  |  |   changeFn: (value: any) => void; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   writeValue(value: any) { this.model = value; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   registerOnChange(fn: (value: any) => void) { this.changeFn = fn; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   registerOnTouched() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   setDisabledState(isDisabled: boolean) { this.isDisabled = isDisabled; } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-custom-wrapper', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <form> | 
					
						
							|  |  |  |        <ng-model-custom-comp name="name" [(ngModel)]="name" [disabled]="isDisabled"></ng-model-custom-comp> | 
					
						
							|  |  |  |     </form> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelCustomWrapper { | 
					
						
							|  |  |  |   name: string; | 
					
						
							|  |  |  |   isDisabled = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 11:33:49 -07:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-validation-bindings', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <form> | 
					
						
							|  |  |  |       <input name="required" ngModel  [required]="required"> | 
					
						
							|  |  |  |       <input name="minlength" ngModel  [minlength]="minLen"> | 
					
						
							|  |  |  |       <input name="maxlength" ngModel [maxlength]="maxLen"> | 
					
						
							|  |  |  |       <input name="pattern" ngModel  [pattern]="pattern"> | 
					
						
							|  |  |  |     </form> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelValidationBindings { | 
					
						
							|  |  |  |   required: boolean; | 
					
						
							|  |  |  |   minLen: number; | 
					
						
							|  |  |  |   maxLen: number; | 
					
						
							|  |  |  |   pattern: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-10 18:17:45 +02:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-multiple-validators', | 
					
						
							|  |  |  |   template: `
 | 
					
						
							|  |  |  |     <form> | 
					
						
							|  |  |  |       <input name="tovalidate" ngModel  [required]="required" [minlength]="minLen" [pattern]="pattern"> | 
					
						
							|  |  |  |     </form> | 
					
						
							|  |  |  |   `
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelMultipleValidators { | 
					
						
							|  |  |  |   required: boolean; | 
					
						
							|  |  |  |   minLen: number; | 
					
						
							| 
									
										
										
										
											2016-11-16 05:48:34 +03:00
										 |  |  |   pattern: string|RegExp; | 
					
						
							| 
									
										
										
										
											2016-10-10 18:17:45 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-10 13:44:04 +03:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-checkbox-validator', | 
					
						
							|  |  |  |   template: | 
					
						
							|  |  |  |       `<form><input type="checkbox" [(ngModel)]="accepted" [required]="required" name="checkbox"></form>` | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelCheckboxRequiredValidator { | 
					
						
							|  |  |  |   accepted: boolean = false; | 
					
						
							|  |  |  |   required: boolean = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-29 20:07:02 +03:00
										 |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-email', | 
					
						
							|  |  |  |   template: `<form><input type="email" ngModel [email]="validatorEnabled" name="email"></form>` | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelEmailValidator { | 
					
						
							|  |  |  |   validatorEnabled: boolean = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-19 18:56:31 +02:00
										 |  |  | @Directive({ | 
					
						
							|  |  |  |   selector: '[ng-async-validator]', | 
					
						
							|  |  |  |   providers: [ | 
					
						
							|  |  |  |     {provide: NG_ASYNC_VALIDATORS, useExisting: forwardRef(() => NgAsyncValidator), multi: true} | 
					
						
							|  |  |  |   ] | 
					
						
							|  |  |  | }) | 
					
						
							| 
									
										
										
										
											2017-02-21 03:26:51 +03:00
										 |  |  | class NgAsyncValidator implements AsyncValidator { | 
					
						
							| 
									
										
										
										
											2016-10-19 18:56:31 +02:00
										 |  |  |   validate(c: AbstractControl) { return Promise.resolve(null); } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'ng-model-async-validation', | 
					
						
							|  |  |  |   template: `<input name="async" ngModel ng-async-validator>` | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | class NgModelAsyncValidation { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 16:37:59 -07:00
										 |  |  | function sortedClassList(el: HTMLElement) { | 
					
						
							| 
									
										
										
										
											2016-09-09 12:04:38 -07:00
										 |  |  |   const l = getDOM().classList(el); | 
					
						
							|  |  |  |   l.sort(); | 
					
						
							| 
									
										
										
										
											2016-07-25 15:57:51 -07:00
										 |  |  |   return l; | 
					
						
							|  |  |  | } |