Skip to content

Commit 3983080

Browse files
alxhubmattrbeck
authored andcommitted
feat(forms): support ngNoCva as an opt-out for ControlValueAccessors
If `FormsModule` or `ReactiveFormsModule` is present in the scope of a template, plain `<input>` and other form elements will get default CVA directives added. This commit adds an `ngNoCva` attribute as a negative selector for those directives, so `<input ngNoCva>` elements will not have them matched.
1 parent b18592a commit 3983080

File tree

8 files changed

+14
-14
lines changed

8 files changed

+14
-14
lines changed

goldens/public-api/forms/index.api.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ export interface AsyncValidatorFn {
207207
export class CheckboxControlValueAccessor extends BuiltInControlValueAccessor implements ControlValueAccessor {
208208
writeValue(value: any): void;
209209
// (undocumented)
210-
static ɵdir: i0.ɵɵDirectiveDeclaration<CheckboxControlValueAccessor, "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]", never, {}, {}, never, never, false, never>;
210+
static ɵdir: i0.ɵɵDirectiveDeclaration<CheckboxControlValueAccessor, "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]", never, {}, {}, never, never, false, never>;
211211
// (undocumented)
212212
static ɵfac: i0.ɵɵFactoryDeclaration<CheckboxControlValueAccessor, never>;
213213
}
@@ -255,7 +255,7 @@ export class DefaultValueAccessor extends BaseControlValueAccessor implements Co
255255
constructor(renderer: Renderer2, elementRef: ElementRef, _compositionMode: boolean);
256256
writeValue(value: any): void;
257257
// (undocumented)
258-
static ɵdir: i0.ɵɵDirectiveDeclaration<DefaultValueAccessor, "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]", never, {}, {}, never, never, false, never>;
258+
static ɵdir: i0.ɵɵDirectiveDeclaration<DefaultValueAccessor, "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]", never, {}, {}, never, never, false, never>;
259259
// (undocumented)
260260
static ɵfac: i0.ɵɵFactoryDeclaration<DefaultValueAccessor, [null, null, { optional: true; }]>;
261261
}
@@ -804,7 +804,7 @@ export class NumberValueAccessor extends BuiltInControlValueAccessor implements
804804
registerOnChange(fn: (_: number | null) => void): void;
805805
writeValue(value: number): void;
806806
// (undocumented)
807-
static ɵdir: i0.ɵɵDirectiveDeclaration<NumberValueAccessor, "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]", never, {}, {}, never, never, false, never>;
807+
static ɵdir: i0.ɵɵDirectiveDeclaration<NumberValueAccessor, "input[type=number]:not([ngNoCva])[formControlName],input[type=number]:not([ngNoCva])[formControl],input[type=number]:not([ngNoCva])[ngModel]", never, {}, {}, never, never, false, never>;
808808
// (undocumented)
809809
static ɵfac: i0.ɵɵFactoryDeclaration<NumberValueAccessor, never>;
810810
}
@@ -841,7 +841,7 @@ export class RadioControlValueAccessor extends BuiltInControlValueAccessor imple
841841
value: any;
842842
writeValue(value: any): void;
843843
// (undocumented)
844-
static ɵdir: i0.ɵɵDirectiveDeclaration<RadioControlValueAccessor, "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", never, { "name": { "alias": "name"; "required": false; }; "formControlName": { "alias": "formControlName"; "required": false; }; "value": { "alias": "value"; "required": false; }; }, {}, never, never, false, never>;
844+
static ɵdir: i0.ɵɵDirectiveDeclaration<RadioControlValueAccessor, "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", never, { "name": { "alias": "name"; "required": false; }; "formControlName": { "alias": "formControlName"; "required": false; }; "value": { "alias": "value"; "required": false; }; }, {}, never, never, false, never>;
845845
// (undocumented)
846846
static ɵfac: i0.ɵɵFactoryDeclaration<RadioControlValueAccessor, never>;
847847
}
@@ -851,7 +851,7 @@ export class RangeValueAccessor extends BuiltInControlValueAccessor implements C
851851
registerOnChange(fn: (_: number | null) => void): void;
852852
writeValue(value: any): void;
853853
// (undocumented)
854-
static ɵdir: i0.ɵɵDirectiveDeclaration<RangeValueAccessor, "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]", never, {}, {}, never, never, false, never>;
854+
static ɵdir: i0.ɵɵDirectiveDeclaration<RangeValueAccessor, "input[type=range]:not([ngNoCva])[formControlName],input[type=range]:not([ngNoCva])[formControl],input[type=range]:not([ngNoCva])[ngModel]", never, {}, {}, never, never, false, never>;
855855
// (undocumented)
856856
static ɵfac: i0.ɵɵFactoryDeclaration<RangeValueAccessor, never>;
857857
}
@@ -887,7 +887,7 @@ export class SelectControlValueAccessor extends BuiltInControlValueAccessor impl
887887
value: any;
888888
writeValue(value: any): void;
889889
// (undocumented)
890-
static ɵdir: i0.ɵɵDirectiveDeclaration<SelectControlValueAccessor, "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", never, { "compareWith": { "alias": "compareWith"; "required": false; }; }, {}, never, never, false, never>;
890+
static ɵdir: i0.ɵɵDirectiveDeclaration<SelectControlValueAccessor, "select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]", never, { "compareWith": { "alias": "compareWith"; "required": false; }; }, {}, never, never, false, never>;
891891
// (undocumented)
892892
static ɵfac: i0.ɵɵFactoryDeclaration<SelectControlValueAccessor, never>;
893893
}
@@ -899,7 +899,7 @@ export class SelectMultipleControlValueAccessor extends BuiltInControlValueAcces
899899
value: any;
900900
writeValue(value: any): void;
901901
// (undocumented)
902-
static ɵdir: i0.ɵɵDirectiveDeclaration<SelectMultipleControlValueAccessor, "select[multiple][formControlName],select[multiple][formControl],select[multiple][ngModel]", never, { "compareWith": { "alias": "compareWith"; "required": false; }; }, {}, never, never, false, never>;
902+
static ɵdir: i0.ɵɵDirectiveDeclaration<SelectMultipleControlValueAccessor, "select[multiple]:not([ngNoCva])[formControlName],select[multiple]:not([ngNoCva])[formControl],select[multiple]:not([ngNoCva])[ngModel]", never, { "compareWith": { "alias": "compareWith"; "required": false; }; }, {}, never, never, false, never>;
903903
// (undocumented)
904904
static ɵfac: i0.ɵɵFactoryDeclaration<SelectMultipleControlValueAccessor, never>;
905905
}

packages/forms/src/directives/checkbox_value_accessor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const CHECKBOX_VALUE_ACCESSOR: Provider = {
4545
*/
4646
@Directive({
4747
selector:
48-
'input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]',
48+
'input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]',
4949
host: {'(change)': 'onChange($any($event.target).checked)', '(blur)': 'onTouched()'},
5050
providers: [CHECKBOX_VALUE_ACCESSOR],
5151
standalone: false,

packages/forms/src/directives/default_value_accessor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export const COMPOSITION_BUFFER_MODE = new InjectionToken<boolean>(
8585
*/
8686
@Directive({
8787
selector:
88-
'input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]',
88+
'input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]',
8989
// TODO: vsavkin replace the above selector with the one below it once
9090
// https://github.com/angular/angular/issues/3011 is implemented
9191
// selector: '[ngModel],[formControl],[formControlName]',

packages/forms/src/directives/number_value_accessor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const NUMBER_VALUE_ACCESSOR: Provider = {
4646
*/
4747
@Directive({
4848
selector:
49-
'input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]',
49+
'input[type=number]:not([ngNoCva])[formControlName],input[type=number]:not([ngNoCva])[formControl],input[type=number]:not([ngNoCva])[ngModel]',
5050
host: {'(input)': 'onChange($any($event.target).value)', '(blur)': 'onTouched()'},
5151
providers: [NUMBER_VALUE_ACCESSOR],
5252
standalone: false,

packages/forms/src/directives/radio_control_value_accessor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ export class RadioControlRegistry {
121121
*/
122122
@Directive({
123123
selector:
124-
'input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]',
124+
'input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]',
125125
host: {'(change)': 'onChange()', '(blur)': 'onTouched()'},
126126
providers: [RADIO_VALUE_ACCESSOR],
127127
standalone: false,

packages/forms/src/directives/range_value_accessor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const RANGE_VALUE_ACCESSOR: Provider = {
4646
*/
4747
@Directive({
4848
selector:
49-
'input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]',
49+
'input[type=range]:not([ngNoCva])[formControlName],input[type=range]:not([ngNoCva])[formControl],input[type=range]:not([ngNoCva])[ngModel]',
5050
host: {
5151
'(change)': 'onChange($any($event.target).value)',
5252
'(input)': 'onChange($any($event.target).value)',

packages/forms/src/directives/select_control_value_accessor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ function _extractId(valueString: string): string {
106106
*/
107107
@Directive({
108108
selector:
109-
'select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]',
109+
'select:not([multiple]):not([ngNoCva])[formControlName],select:not([multiple]):not([ngNoCva])[formControl],select:not([multiple]):not([ngNoCva])[ngModel]',
110110
host: {'(change)': 'onChange($any($event.target).value)', '(blur)': 'onTouched()'},
111111
providers: [SELECT_VALUE_ACCESSOR],
112112
standalone: false,

packages/forms/src/directives/select_multiple_control_value_accessor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ function _extractId(valueString: string): string {
8181
*/
8282
@Directive({
8383
selector:
84-
'select[multiple][formControlName],select[multiple][formControl],select[multiple][ngModel]',
84+
'select[multiple]:not([ngNoCva])[formControlName],select[multiple]:not([ngNoCva])[formControl],select[multiple]:not([ngNoCva])[ngModel]',
8585
host: {'(change)': 'onChange($event.target)', '(blur)': 'onTouched()'},
8686
providers: [SELECT_MULTIPLE_VALUE_ACCESSOR],
8787
standalone: false,

0 commit comments

Comments
 (0)