Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c001b05

Browse files
fdonzelloAndrewKushnir
authored andcommitted
refactor(forms): added control name in console errors (#55397)
When a formControlName is used without a parent formGroup, an error is logged in the console. Before this commit, there was no information about which control had the issue. Now, it's reported and the troubleshoot is much faster. PR Close #55397
1 parent c175bca commit c001b05

File tree

3 files changed

+72
-6
lines changed

3 files changed

+72
-6
lines changed

‎packages/forms/src/directives/reactive_directives/form_control_name.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ export class FormControlName extends NgControl implements OnChanges, OnDestroy {
221221
!(this._parent instanceof FormGroupDirective) &&
222222
!(this._parent instanceof FormArrayName)
223223
) {
224-
throw controlParentException();
224+
throw controlParentException(this.name);
225225
}
226226
}
227227
}

‎packages/forms/src/directives/reactive_errors.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,30 @@ import {
1717
ngModelGroupExample,
1818
} from './error_examples';
1919

20-
export function controlParentException(): Error {
20+
export function controlParentException(nameOrIndex: string | number | null): Error {
2121
return new RuntimeError(
2222
RuntimeErrorCode.FORM_CONTROL_NAME_MISSING_PARENT,
23-
`formControlName must be used with a parent formGroup directive. You'll want to add a formGroup
23+
`formControlName must be used with a parent formGroup directive. You'll want to add a formGroup
2424
directive and pass it an existing FormGroup instance (you can create one in your class).
2525
26+
${describeFormControl(nameOrIndex)}
27+
2628
Example:
2729
2830
${formControlNameExample}`,
2931
);
3032
}
3133

34+
function describeFormControl(nameOrIndex: string | number | null): string {
35+
if (nameOrIndex == null || nameOrIndex === '') {
36+
return '';
37+
}
38+
39+
const valueType = typeof nameOrIndex === 'string' ? 'name' : 'index';
40+
41+
return `Affected Form Control ${valueType}: "${nameOrIndex}"`;
42+
}
43+
3244
export function ngModelGroupException(): Error {
3345
return new RuntimeError(
3446
RuntimeErrorCode.FORM_CONTROL_NAME_INSIDE_MODEL_GROUP,

‎packages/forms/test/reactive_integration_spec.ts

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3881,11 +3881,65 @@ describe('reactive forms integration tests', () => {
38813881
`,
38823882
},
38833883
});
3884+
38843885
const fixture = initTest(FormGroupComp);
3886+
expect(() => fixture.detectChanges()).toThrowMatching((e: Error) => {
3887+
if (!e.message.includes(`formControlName must be used with a parent formGroup directive`)) {
3888+
return false;
3889+
}
38853890

3886-
expect(() => fixture.detectChanges()).toThrowError(
3887-
new RegExp(`formControlName must be used with a parent formGroup directive`),
3888-
);
3891+
if (!e.message.includes(`Affected Form Control name: "login"`)) {
3892+
return false;
3893+
}
3894+
3895+
return true;
3896+
});
3897+
});
3898+
3899+
it('should throw if formControlName, with an index, is used without a control container', () => {
3900+
TestBed.overrideComponent(FormGroupComp, {
3901+
set: {
3902+
template: `
3903+
<input type="text" [formControlName]="0">
3904+
`,
3905+
},
3906+
});
3907+
3908+
const fixture = initTest(FormGroupComp);
3909+
expect(() => fixture.detectChanges()).toThrowMatching((e: Error) => {
3910+
if (!e.message.includes(`formControlName must be used with a parent formGroup directive`)) {
3911+
return false;
3912+
}
3913+
3914+
if (!e.message.includes(`Affected Form Control index: "0"`)) {
3915+
return false;
3916+
}
3917+
3918+
return true;
3919+
});
3920+
});
3921+
3922+
it('should throw, without indicating the affected form control, if formControlName is used without a control container', () => {
3923+
TestBed.overrideComponent(FormGroupComp, {
3924+
set: {
3925+
template: `
3926+
<input type="text" formControlName>
3927+
`,
3928+
},
3929+
});
3930+
3931+
const fixture = initTest(FormGroupComp);
3932+
expect(() => fixture.detectChanges()).toThrowMatching((e: Error) => {
3933+
if (!e.message.includes(`formControlName must be used with a parent formGroup directive`)) {
3934+
return false;
3935+
}
3936+
3937+
if (e.message.includes(`Affected Form Control`)) {
3938+
return false;
3939+
}
3940+
3941+
return true;
3942+
});
38893943
});
38903944

38913945
it('should throw if formControlName is used with NgForm', () => {

0 commit comments

Comments
 (0)