refactor(forms): remove ngForm element selector (#33058)
Removes the deprecated `ngForm` element selector and all of the code related to it. BREAKING CHANGES: * `<ngForm></ngForm>` can no longer be used as a selector. Use `<ng-form></ng-form>` instead. * The `NgFromSelectorWarning` directive has been removed. * `FormsModule.withConfig` has been removed. Use the `FormsModule` directly. PR Close #33058
This commit is contained in:
		
							parent
							
								
									15e3b5f531
								
							
						
					
					
						commit
						0b1daa9ebd
					
				| @ -41,8 +41,6 @@ v8 - v11 | ||||
| | `@angular/core` | [`ReflectiveKey`](#core) | <!--v8--> v9 | | ||||
| | `@angular/core` | [`RenderComponentType`](#core) | <!--v7--> v9 | | ||||
| | `@angular/core` | [`ViewEncapsulation.Native`](#core) | v9 | | ||||
| | `@angular/forms` | [`ngForm` element selector](#ngform) | v9 | | ||||
| | `@angular/forms` | [`NgFormSelectorWarning`](#forms) | v9 | | ||||
| | `@angular/forms` | [`ngModel` with reactive forms](#ngmodel-reactive) | v9 | | ||||
| | `@angular/router` | [`preserveQueryParams`](#router) | <!--v7--> v9 | | ||||
| | `@angular/upgrade` | [`@angular/upgrade`](#upgrade) | <!--v8--> v9 | | ||||
| @ -107,7 +105,6 @@ Tip: In the [API reference section](api) of this doc site, deprecated APIs are i | ||||
| 
 | ||||
| | API | Replacement | Deprecation announced | Notes | | ||||
| | --- | ----------- | --------------------- | ----- | | ||||
| | [`NgFormSelectorWarning`](api/forms/NgFormSelectorWarning) | n/a | v6 | See [ngForm](#ngform). | | ||||
| 
 | ||||
| {@a router} | ||||
| ### @angular/router | ||||
| @ -176,27 +173,6 @@ The `<template>` tag was deprecated in v4 to avoid colliding with the DOM's elem | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| {@a ngform} | ||||
| ### ngForm element selector | ||||
| 
 | ||||
| Support for using `ngForm` element selector was deprecated in v6. | ||||
| It has been deprecated to be consistent with other core Angular selectors, which are typically written in kebab-case. | ||||
| 
 | ||||
| Deprecated: | ||||
| 
 | ||||
| ``` | ||||
| <ngForm #myForm="ngForm"> | ||||
| ``` | ||||
| 
 | ||||
| Replacement: | ||||
| 
 | ||||
| ``` | ||||
| <ng-form #myForm="ngForm"> | ||||
| ``` | ||||
| 
 | ||||
| The [`NgFormSelectorWarning`](api/forms/NgFormSelectorWarning) directive is solely used to display warnings when the deprecated `ngForm` selector is used. | ||||
| 
 | ||||
| 
 | ||||
| {@a ngmodel-reactive} | ||||
| ### ngModel with reactive forms | ||||
| 
 | ||||
| @ -405,9 +381,17 @@ The following APIs have been removed starting with version 8.0.0: | ||||
| | `@angular/core/testing` | [`TestBed.deprecatedOverrideProvider()`](https://v7.angular.io/api/core/testing/TestBed#deprecatedoverrideprovider) | [`TestBed.overrideProvider()`](api/core/testing/TestBed#overrideprovider) | none | | ||||
| | `@angular/core/testing` | [`TestBedStatic.deprecatedOverrideProvider()`](https://v7.angular.io/api/core/testing/TestBedStatic#deprecatedoverrideprovider) | [`TestBedStatic.overrideProvider()`](api/core/testing/TestBedStatic#overrideprovider) | none | | ||||
| | `@angular/service-worker` | `versionedFiles` | `files` | In the service worker configuration file `ngsw-config.json`, replace `versionedFiles` with `files`. See [Service Worker Configuration](guide/service-worker-config#assetgroups). | | ||||
| | `@angular/core` | [`Renderer`](https://v8.angular.io/api/core/Renderer) | [`Renderer2`](https://angular.io/api/core/Renderer2) | [Migration guide.](guide/migration-renderer) | ||||
| | `@angular/core` | [`RootRenderer`](https://v8.angular.io/api/core/RootRenderer) | [`RendererFactory2`](https://angular.io/api/core/RendererFactory2) | none | ||||
| | `@angular/core` | [`RenderComponentType`](https://v8.angular.io/api/core/RenderComponentType) | [`RendererType2`](https://angular.io/api/core/RendererType2) | none | ||||
| 
 | ||||
| 
 | ||||
| The following APIs have been removed starting with version 9.0.0: | ||||
| 
 | ||||
| | Package | API            | Replacement | Notes | | ||||
| | ------- | -------------- | ----------- | ----- | | ||||
| | `@angular/core`  | [`Renderer`](https://v8.angular.io/api/core/Renderer) | [`Renderer2`](https://angular.io/api/core/Renderer2) | [Migration guide.](guide/migration-renderer) | ||||
| | `@angular/core`  | [`RootRenderer`](https://v8.angular.io/api/core/RootRenderer) | [`RendererFactory2`](https://angular.io/api/core/RendererFactory2) | none | ||||
| | `@angular/core`  | [`RenderComponentType`](https://v8.angular.io/api/core/RenderComponentType) | [`RendererType2`](https://angular.io/api/core/RendererType2) | none | ||||
| | `@angular/forms` | [`NgFormSelectorWarning`](https://v8.angular.io/api/forms/NgFormSelectorWarning) | none | none | ||||
| | `@angular/forms` | `ngForm` element selector | `ng-form` element selector | none | ||||
| 
 | ||||
| 
 | ||||
| <!-- The following anchor is used by redirects from the removed API pages. Do not change or remove. --> | ||||
|  | ||||
| @ -12,7 +12,6 @@ import {CheckboxControlValueAccessor} from './directives/checkbox_value_accessor | ||||
| import {DefaultValueAccessor} from './directives/default_value_accessor'; | ||||
| import {NgControlStatus, NgControlStatusGroup} from './directives/ng_control_status'; | ||||
| import {NgForm} from './directives/ng_form'; | ||||
| import {NgFormSelectorWarning} from './directives/ng_form_selector_warning'; | ||||
| import {NgModel} from './directives/ng_model'; | ||||
| import {NgModelGroup} from './directives/ng_model_group'; | ||||
| import {NgNoValidate} from './directives/ng_no_validate_directive'; | ||||
| @ -33,7 +32,6 @@ export {DefaultValueAccessor} from './directives/default_value_accessor'; | ||||
| export {NgControl} from './directives/ng_control'; | ||||
| export {NgControlStatus, NgControlStatusGroup} from './directives/ng_control_status'; | ||||
| export {NgForm} from './directives/ng_form'; | ||||
| export {NG_FORM_SELECTOR_WARNING, NgFormSelectorWarning} from './directives/ng_form_selector_warning'; | ||||
| export {NgModel} from './directives/ng_model'; | ||||
| export {NgModelGroup} from './directives/ng_model_group'; | ||||
| export {NumberValueAccessor} from './directives/number_value_accessor'; | ||||
| @ -67,8 +65,7 @@ export const SHARED_FORM_DIRECTIVES: Type<any>[] = [ | ||||
|   EmailValidator, | ||||
| ]; | ||||
| 
 | ||||
| export const TEMPLATE_DRIVEN_DIRECTIVES: Type<any>[] = | ||||
|     [NgModel, NgModelGroup, NgForm, NgFormSelectorWarning]; | ||||
| export const TEMPLATE_DRIVEN_DIRECTIVES: Type<any>[] = [NgModel, NgModelGroup, NgForm]; | ||||
| 
 | ||||
| export const REACTIVE_DRIVEN_DIRECTIVES: Type<any>[] = | ||||
|     [FormControlDirective, FormGroupDirective, FormControlName, FormGroupName, FormArrayName]; | ||||
|  | ||||
| @ -94,7 +94,7 @@ const resolvedPromise = (() => Promise.resolve(null))(); | ||||
|  * @publicApi | ||||
|  */ | ||||
| @Directive({ | ||||
|   selector: 'form:not([ngNoForm]):not([formGroup]),ngForm,ng-form,[ngForm]', | ||||
|   selector: 'form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]', | ||||
|   providers: [formDirectiveProvider], | ||||
|   host: {'(submit)': 'onSubmit($event)', '(reset)': 'onReset()'}, | ||||
|   outputs: ['ngSubmit'], | ||||
|  | ||||
| @ -1,42 +0,0 @@ | ||||
| /** | ||||
|  * @license | ||||
|  * Copyright Google Inc. All Rights Reserved. | ||||
|  * | ||||
|  * Use of this source code is governed by an MIT-style license that can be | ||||
|  * found in the LICENSE file at https://angular.io/license
 | ||||
|  */ | ||||
| 
 | ||||
| import {Directive, Inject, InjectionToken, Optional} from '@angular/core'; | ||||
| import {TemplateDrivenErrors} from './template_driven_errors'; | ||||
| 
 | ||||
| /** | ||||
|  * @description | ||||
|  * `InjectionToken` to provide to turn off the warning when using 'ngForm' deprecated selector. | ||||
|  */ | ||||
| export const NG_FORM_SELECTOR_WARNING = new InjectionToken('NgFormSelectorWarning'); | ||||
| 
 | ||||
| /** | ||||
|  * This directive is solely used to display warnings when the deprecated `ngForm` selector is used. | ||||
|  * | ||||
|  * @deprecated in Angular v6 and will be removed in Angular v9. | ||||
|  * @ngModule FormsModule | ||||
|  * @publicApi | ||||
|  */ | ||||
| @Directive({selector: 'ngForm'}) | ||||
| export class NgFormSelectorWarning { | ||||
|   /** | ||||
|    * Static property used to track whether the deprecation warning for this selector has been sent. | ||||
|    * Used to support warning config of "once". | ||||
|    * | ||||
|    * @internal | ||||
|    */ | ||||
|   static _ngFormWarning = false; | ||||
| 
 | ||||
|   constructor(@Optional() @Inject(NG_FORM_SELECTOR_WARNING) ngFormWarning: string|null) { | ||||
|     if (((!ngFormWarning || ngFormWarning === 'once') && !NgFormSelectorWarning._ngFormWarning) || | ||||
|         ngFormWarning === 'always') { | ||||
|       TemplateDrivenErrors.ngFormWarning(); | ||||
|       NgFormSelectorWarning._ngFormWarning = true; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -57,21 +57,4 @@ export class TemplateDrivenErrors { | ||||
| 
 | ||||
|       ${Examples.ngModelGroup}`);
 | ||||
|   } | ||||
| 
 | ||||
|   static ngFormWarning() { | ||||
|     console.warn(` | ||||
|     It looks like you're using 'ngForm'. | ||||
| 
 | ||||
|     Support for using the 'ngForm' element selector has been deprecated in Angular v6 and will be removed | ||||
|     in Angular v9. | ||||
| 
 | ||||
|     Use 'ng-form' instead. | ||||
| 
 | ||||
|     Before: | ||||
|     <ngForm #myForm="ngForm"> | ||||
| 
 | ||||
|     After: | ||||
|     <ng-form #myForm="ngForm"> | ||||
|     `);
 | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -8,7 +8,7 @@ | ||||
| 
 | ||||
| import {ModuleWithProviders, NgModule} from '@angular/core'; | ||||
| 
 | ||||
| import {InternalFormsSharedModule, NG_FORM_SELECTOR_WARNING, NG_MODEL_WITH_FORM_CONTROL_WARNING, REACTIVE_DRIVEN_DIRECTIVES, TEMPLATE_DRIVEN_DIRECTIVES} from './directives'; | ||||
| import {InternalFormsSharedModule, NG_MODEL_WITH_FORM_CONTROL_WARNING, REACTIVE_DRIVEN_DIRECTIVES, TEMPLATE_DRIVEN_DIRECTIVES} from './directives'; | ||||
| import {RadioControlRegistry} from './directives/radio_control_value_accessor'; | ||||
| import {FormBuilder} from './form_builder'; | ||||
| 
 | ||||
| @ -26,23 +26,6 @@ import {FormBuilder} from './form_builder'; | ||||
|   exports: [InternalFormsSharedModule, TEMPLATE_DRIVEN_DIRECTIVES] | ||||
| }) | ||||
| export class FormsModule { | ||||
|   /** | ||||
|    * @description | ||||
|    * Provides options for configuring the template-driven forms module. | ||||
|    * | ||||
|    * @param opts An object of configuration options | ||||
|    * * `warnOnDeprecatedNgFormSelector` Configures when to emit a warning when the deprecated | ||||
|    * `ngForm` selector is used. | ||||
|    */ | ||||
|   static withConfig(opts: { | ||||
|     /** @deprecated as of v6 */ warnOnDeprecatedNgFormSelector?: 'never' | 'once' | 'always', | ||||
|   }): ModuleWithProviders<FormsModule> { | ||||
|     return { | ||||
|       ngModule: FormsModule, | ||||
|       providers: | ||||
|           [{provide: NG_FORM_SELECTOR_WARNING, useValue: opts.warnOnDeprecatedNgFormSelector}] | ||||
|     }; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  | ||||
| @ -29,7 +29,6 @@ export {Form} from './directives/form_interface'; | ||||
| export {NgControl} from './directives/ng_control'; | ||||
| export {NgControlStatus, NgControlStatusGroup} from './directives/ng_control_status'; | ||||
| export {NgForm} from './directives/ng_form'; | ||||
| export {NgFormSelectorWarning} from './directives/ng_form_selector_warning'; | ||||
| export {NgModel} from './directives/ng_model'; | ||||
| export {NgModelGroup} from './directives/ng_model_group'; | ||||
| export {ɵNgNoValidate} from './directives/ng_no_validate_directive'; | ||||
|  | ||||
| @ -9,7 +9,7 @@ | ||||
| import {ɵgetDOM as getDOM} from '@angular/common'; | ||||
| import {Component, Directive, Type, forwardRef} from '@angular/core'; | ||||
| import {ComponentFixture, TestBed, async, fakeAsync, tick} from '@angular/core/testing'; | ||||
| import {AbstractControl, AsyncValidator, COMPOSITION_BUFFER_MODE, FormControl, FormsModule, NG_ASYNC_VALIDATORS, NgForm, NgFormSelectorWarning, NgModel} from '@angular/forms'; | ||||
| import {AbstractControl, AsyncValidator, COMPOSITION_BUFFER_MODE, FormControl, FormsModule, NG_ASYNC_VALIDATORS, NgForm, NgModel} from '@angular/forms'; | ||||
| import {By} from '@angular/platform-browser/src/dom/debug/by'; | ||||
| import {dispatchEvent, sortedClassList} from '@angular/platform-browser/testing/src/browser_util'; | ||||
| import {merge} from 'rxjs'; | ||||
| @ -1630,61 +1630,6 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat | ||||
|          })); | ||||
|     }); | ||||
| 
 | ||||
|     describe('ngForm deprecation warnings', () => { | ||||
|       let warnSpy: jasmine.Spy; | ||||
| 
 | ||||
|       @Component({selector: 'ng-form-deprecated', template: `<ngForm></ngForm><ngForm></ngForm>`}) | ||||
|       class ngFormDeprecated { | ||||
|       } | ||||
| 
 | ||||
|       beforeEach(() => { | ||||
|         (NgFormSelectorWarning as any)._ngFormWarning = false; | ||||
| 
 | ||||
|         warnSpy = spyOn(console, 'warn'); | ||||
|       }); | ||||
| 
 | ||||
|       describe(`when using the deprecated 'ngForm' selector`, () => { | ||||
|         it(`should only warn once when global provider is provided with "once"`, () => { | ||||
|           TestBed.configureTestingModule({ | ||||
|             declarations: [ngFormDeprecated], | ||||
|             imports: [FormsModule.withConfig({warnOnDeprecatedNgFormSelector: 'once'})] | ||||
|           }); | ||||
|           TestBed.createComponent(ngFormDeprecated); | ||||
|           expect(warnSpy).toHaveBeenCalledTimes(1); | ||||
|           expect(warnSpy.calls.mostRecent().args[0]) | ||||
|               .toMatch(/It looks like you're using 'ngForm'/gi); | ||||
|         }); | ||||
| 
 | ||||
|         it(`should only warn once by default`, () => { | ||||
|           initTest(ngFormDeprecated); | ||||
|           expect(warnSpy).toHaveBeenCalledTimes(1); | ||||
|           expect(warnSpy.calls.mostRecent().args[0]) | ||||
|               .toMatch(/It looks like you're using 'ngForm'/gi); | ||||
|         }); | ||||
| 
 | ||||
|         it(`should not warn when global provider is provided with "never"`, () => { | ||||
|           TestBed.configureTestingModule({ | ||||
|             declarations: [ngFormDeprecated], | ||||
|             imports: [FormsModule.withConfig({warnOnDeprecatedNgFormSelector: 'never'})] | ||||
|           }); | ||||
|           TestBed.createComponent(ngFormDeprecated); | ||||
|           expect(warnSpy).not.toHaveBeenCalled(); | ||||
|         }); | ||||
| 
 | ||||
|         it(`should only warn for each instance when global provider is provided with "always"`, | ||||
|            () => { | ||||
|              TestBed.configureTestingModule({ | ||||
|                declarations: [ngFormDeprecated], | ||||
|                imports: [FormsModule.withConfig({warnOnDeprecatedNgFormSelector: 'always'})] | ||||
|              }); | ||||
| 
 | ||||
|              TestBed.createComponent(ngFormDeprecated); | ||||
|              expect(warnSpy).toHaveBeenCalledTimes(2); | ||||
|              expect(warnSpy.calls.mostRecent().args[0]) | ||||
|                  .toMatch(/It looks like you're using 'ngForm'/gi); | ||||
|            }); | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										7
									
								
								tools/public_api_guard/forms/forms.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								tools/public_api_guard/forms/forms.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -327,8 +327,6 @@ export declare class FormGroupName extends AbstractFormGroupDirective implements | ||||
| } | ||||
| 
 | ||||
| export declare class FormsModule { | ||||
|     static withConfig(opts: { warnOnDeprecatedNgFormSelector?: 'never' | 'once' | 'always'; | ||||
|     }): ModuleWithProviders<FormsModule>; | ||||
| } | ||||
| 
 | ||||
| export declare class MaxLengthValidator implements Validator, OnChanges { | ||||
| @ -397,11 +395,6 @@ export declare class NgForm extends ControlContainer implements Form, AfterViewI | ||||
|     updateModel(dir: NgControl, value: any): void; | ||||
| } | ||||
| 
 | ||||
| /** @deprecated */ | ||||
| export declare class NgFormSelectorWarning { | ||||
|     constructor(ngFormWarning: string | null); | ||||
| } | ||||
| 
 | ||||
| export declare class NgModel extends NgControl implements OnChanges, OnDestroy { | ||||
|     readonly asyncValidator: AsyncValidatorFn | null; | ||||
|     readonly control: FormControl; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user