Revert "feat(forms): add ng-submitted
class to forms that have been submitted." (#42474)
This reverts commit f024d7556081f8913f21761bb8e6aab8d08be110. PR Close #42474
This commit is contained in:
parent
ae858c0504
commit
00b1444d12
@ -195,7 +195,6 @@ The following classes are currently supported.
|
|||||||
* `.ng-dirty`
|
* `.ng-dirty`
|
||||||
* `.ng-untouched`
|
* `.ng-untouched`
|
||||||
* `.ng-touched`
|
* `.ng-touched`
|
||||||
* `.ng-submitted` (enclosing form element only)
|
|
||||||
|
|
||||||
In the following example, the hero form uses the `.ng-valid` and `.ng-invalid` classes to
|
In the following example, the hero form uses the `.ng-valid` and `.ng-invalid` classes to
|
||||||
set the color of each form control's border.
|
set the color of each form control's border.
|
||||||
|
@ -314,8 +314,6 @@ Angular sets special CSS classes on the control element to reflect the state, as
|
|||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
Additionally, Angular applies the `ng-submitted` class to `<form>` elements upon submission. This class does *not* apply to inner controls.
|
|
||||||
|
|
||||||
You use these CSS classes to define the styles for your control based on its status.
|
You use these CSS classes to define the styles for your control based on its status.
|
||||||
|
|
||||||
### Observe control states
|
### Observe control states
|
||||||
|
2
goldens/public-api/forms/forms.d.ts
vendored
2
goldens/public-api/forms/forms.d.ts
vendored
@ -460,7 +460,7 @@ export declare class RadioControlValueAccessor extends ɵangular_packages_forms_
|
|||||||
name: string;
|
name: string;
|
||||||
onChange: () => void;
|
onChange: () => void;
|
||||||
value: any;
|
value: any;
|
||||||
constructor(renderer: Renderer2, elementRef: ElementRef, _registry: ɵangular_packages_forms_forms_r, _injector: Injector);
|
constructor(renderer: Renderer2, elementRef: ElementRef, _registry: ɵangular_packages_forms_forms_q, _injector: Injector);
|
||||||
fireUncheck(value: any): void;
|
fireUncheck(value: any): void;
|
||||||
ngOnDestroy(): void;
|
ngOnDestroy(): void;
|
||||||
ngOnInit(): void;
|
ngOnInit(): void;
|
||||||
|
@ -12,8 +12,7 @@ import {AbstractControlDirective} from './abstract_control_directive';
|
|||||||
import {ControlContainer} from './control_container';
|
import {ControlContainer} from './control_container';
|
||||||
import {NgControl} from './ng_control';
|
import {NgControl} from './ng_control';
|
||||||
|
|
||||||
type AnyControlStatus =
|
type AnyControlStatus = 'untouched'|'touched'|'pristine'|'dirty'|'valid'|'invalid'|'pending';
|
||||||
'untouched'|'touched'|'pristine'|'dirty'|'valid'|'invalid'|'pending'|'submitted';
|
|
||||||
|
|
||||||
export class AbstractControlStatus {
|
export class AbstractControlStatus {
|
||||||
private _cd: AbstractControlDirective|null;
|
private _cd: AbstractControlDirective|null;
|
||||||
@ -23,17 +22,6 @@ export class AbstractControlStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
is(status: AnyControlStatus): boolean {
|
is(status: AnyControlStatus): boolean {
|
||||||
// Currently with ViewEngine (in AOT mode) it's not possible to use private methods in host
|
|
||||||
// bindings.
|
|
||||||
// TODO: once ViewEngine is removed, this function should be refactored:
|
|
||||||
// - make the `is` method `protected`, so it's not accessible publicly
|
|
||||||
// - move the `submitted` status logic to the `NgControlStatusGroup` class
|
|
||||||
// and make it `private` or `protected` too.
|
|
||||||
if (status === 'submitted') {
|
|
||||||
// We check for the `submitted` field from `NgForm` and `FormGroupDirective` classes, but
|
|
||||||
// we avoid instanceof checks to prevent non-tree-shakable references to those types.
|
|
||||||
return !!(this._cd as unknown as {submitted: boolean} | null)?.submitted;
|
|
||||||
}
|
|
||||||
return !!this._cd?.control?.[status];
|
return !!this._cd?.control?.[status];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,11 +36,6 @@ export const ngControlStatusHost = {
|
|||||||
'[class.ng-pending]': 'is("pending")',
|
'[class.ng-pending]': 'is("pending")',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ngGroupStatusHost = {
|
|
||||||
...ngControlStatusHost,
|
|
||||||
'[class.ng-submitted]': 'is("submitted")',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
* Directive automatically applied to Angular form controls that sets CSS classes
|
* Directive automatically applied to Angular form controls that sets CSS classes
|
||||||
@ -86,8 +69,7 @@ export class NgControlStatus extends AbstractControlStatus {
|
|||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
* Directive automatically applied to Angular form groups that sets CSS classes
|
* Directive automatically applied to Angular form groups that sets CSS classes
|
||||||
* based on control status (valid/invalid/dirty/etc). On groups, this includes the additional
|
* based on control status (valid/invalid/dirty/etc).
|
||||||
* class ng-submitted.
|
|
||||||
*
|
*
|
||||||
* @see `NgControlStatus`
|
* @see `NgControlStatus`
|
||||||
*
|
*
|
||||||
@ -98,7 +80,7 @@ export class NgControlStatus extends AbstractControlStatus {
|
|||||||
@Directive({
|
@Directive({
|
||||||
selector:
|
selector:
|
||||||
'[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]',
|
'[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]',
|
||||||
host: ngGroupStatusHost
|
host: ngControlStatusHost
|
||||||
})
|
})
|
||||||
export class NgControlStatusGroup extends AbstractControlStatus {
|
export class NgControlStatusGroup extends AbstractControlStatus {
|
||||||
constructor(@Optional() @Self() cd: ControlContainer) {
|
constructor(@Optional() @Self() cd: ControlContainer) {
|
||||||
|
@ -190,7 +190,7 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]');
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should update nested form group model when UI changes', () => {
|
it('should update nested form group model when UI changes', () => {
|
||||||
const fixture = initTest(NestedFormGroupNameComp);
|
const fixture = initTest(NestedFormGroupComp);
|
||||||
fixture.componentInstance.form = new FormGroup(
|
fixture.componentInstance.form = new FormGroup(
|
||||||
{'signin': new FormGroup({'login': new FormControl(), 'password': new FormControl()})});
|
{'signin': new FormGroup({'login': new FormControl(), 'password': new FormControl()})});
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@ -242,7 +242,7 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]');
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should pick up dir validators from nested form groups', () => {
|
it('should pick up dir validators from nested form groups', () => {
|
||||||
const fixture = initTest(NestedFormGroupNameComp, LoginIsEmptyValidator);
|
const fixture = initTest(NestedFormGroupComp, LoginIsEmptyValidator);
|
||||||
const form = new FormGroup({
|
const form = new FormGroup({
|
||||||
'signin': new FormGroup({'login': new FormControl(''), 'password': new FormControl('')})
|
'signin': new FormGroup({'login': new FormControl(''), 'password': new FormControl('')})
|
||||||
});
|
});
|
||||||
@ -260,7 +260,7 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]');
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should strip named controls that are not found', () => {
|
it('should strip named controls that are not found', () => {
|
||||||
const fixture = initTest(NestedFormGroupNameComp, LoginIsEmptyValidator);
|
const fixture = initTest(NestedFormGroupComp, LoginIsEmptyValidator);
|
||||||
const form = new FormGroup({
|
const form = new FormGroup({
|
||||||
'signin': new FormGroup({'login': new FormControl(''), 'password': new FormControl('')})
|
'signin': new FormGroup({'login': new FormControl(''), 'password': new FormControl('')})
|
||||||
});
|
});
|
||||||
@ -335,7 +335,7 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]');
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should attach dirs to all child controls when group control changes', () => {
|
it('should attach dirs to all child controls when group control changes', () => {
|
||||||
const fixture = initTest(NestedFormGroupNameComp, LoginIsEmptyValidator);
|
const fixture = initTest(NestedFormGroupComp, LoginIsEmptyValidator);
|
||||||
const form = new FormGroup({
|
const form = new FormGroup({
|
||||||
signin: new FormGroup(
|
signin: new FormGroup(
|
||||||
{login: new FormControl('oldLogin'), password: new FormControl('oldPassword')})
|
{login: new FormControl('oldLogin'), password: new FormControl('oldPassword')})
|
||||||
@ -1087,8 +1087,6 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]');
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const input = fixture.debugElement.query(By.css('input')).nativeElement;
|
const input = fixture.debugElement.query(By.css('input')).nativeElement;
|
||||||
const formEl = fixture.debugElement.query(By.css('form')).nativeElement;
|
|
||||||
|
|
||||||
expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']);
|
expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']);
|
||||||
|
|
||||||
dispatchEvent(input, 'blur');
|
dispatchEvent(input, 'blur');
|
||||||
@ -1101,19 +1099,6 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]');
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
|
expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
|
||||||
expect(sortedClassList(formEl)).not.toContain('ng-submitted');
|
|
||||||
|
|
||||||
dispatchEvent(formEl, 'submit');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(input)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(formEl)).toContain('ng-submitted');
|
|
||||||
|
|
||||||
dispatchEvent(formEl, 'reset');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(input)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(formEl)).not.toContain('ng-submitted');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work with formGroup', () => {
|
it('should work with formGroup', () => {
|
||||||
@ -1137,126 +1122,6 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]');
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(sortedClassList(formEl)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
|
expect(sortedClassList(formEl)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
|
||||||
|
|
||||||
dispatchEvent(formEl, 'submit');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(formEl)).toContain('ng-submitted');
|
|
||||||
|
|
||||||
dispatchEvent(formEl, 'reset');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(input)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(formEl)).not.toContain('ng-submitted');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not assign `ng-submitted` class to elements with `formArrayName`', () => {
|
|
||||||
// Since element with the `formArrayName` can not represent top-level forms (can only be
|
|
||||||
// inside other elements), this test verifies that these elements never receive
|
|
||||||
// `ng-submitted` CSS class even when they are located inside submitted form.
|
|
||||||
const fixture = initTest(FormArrayComp);
|
|
||||||
const cityArray = new FormArray([new FormControl('SF'), new FormControl('NY')]);
|
|
||||||
const form = new FormGroup({cities: cityArray});
|
|
||||||
fixture.componentInstance.form = form;
|
|
||||||
fixture.componentInstance.cityArray = cityArray;
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const [loginInput, passwordInput] =
|
|
||||||
fixture.debugElement.queryAll(By.css('input')).map(el => el.nativeElement);
|
|
||||||
const arrEl = fixture.debugElement.query(By.css('div')).nativeElement;
|
|
||||||
const formEl = fixture.debugElement.query(By.css('form')).nativeElement;
|
|
||||||
|
|
||||||
expect(passwordInput).toBeDefined();
|
|
||||||
expect(sortedClassList(loginInput)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(arrEl)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(formEl)).not.toContain('ng-submitted');
|
|
||||||
|
|
||||||
dispatchEvent(formEl, 'submit');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(loginInput)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(arrEl)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(formEl)).toContain('ng-submitted');
|
|
||||||
|
|
||||||
dispatchEvent(formEl, 'reset');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(loginInput)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(arrEl)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(formEl)).not.toContain('ng-submitted');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should apply submitted status with nested formArrayName', () => {
|
|
||||||
const fixture = initTest(NestedFormArrayNameComp);
|
|
||||||
const ic = new FormControl('foo');
|
|
||||||
const arr = new FormArray([ic]);
|
|
||||||
const form = new FormGroup({arr});
|
|
||||||
fixture.componentInstance.form = form;
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const input = fixture.debugElement.query(By.css('input')).nativeElement;
|
|
||||||
const arrEl = fixture.debugElement.query(By.css('div')).nativeElement;
|
|
||||||
const formEl = fixture.debugElement.query(By.css('form')).nativeElement;
|
|
||||||
|
|
||||||
expect(sortedClassList(input)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(arrEl)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(formEl)).not.toContain('ng-submitted');
|
|
||||||
|
|
||||||
dispatchEvent(formEl, 'submit');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(input)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(arrEl)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(formEl)).toContain('ng-submitted');
|
|
||||||
|
|
||||||
dispatchEvent(formEl, 'reset');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(input)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(arrEl)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(formEl)).not.toContain('ng-submitted');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should apply submitted status with nested formGroupName', () => {
|
|
||||||
const fixture = initTest(NestedFormGroupNameComp);
|
|
||||||
const loginControl =
|
|
||||||
new FormControl('', {validators: Validators.required, updateOn: 'change'});
|
|
||||||
const passwordControl = new FormControl('', Validators.required);
|
|
||||||
const formGroup = new FormGroup(
|
|
||||||
{signin: new FormGroup({login: loginControl, password: passwordControl})},
|
|
||||||
{updateOn: 'blur'});
|
|
||||||
fixture.componentInstance.form = formGroup;
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const [loginInput, passwordInput] =
|
|
||||||
fixture.debugElement.queryAll(By.css('input')).map(el => el.nativeElement);
|
|
||||||
|
|
||||||
const formEl = fixture.debugElement.query(By.css('form')).nativeElement;
|
|
||||||
const groupEl = fixture.debugElement.query(By.css('div')).nativeElement;
|
|
||||||
loginInput.value = 'Nancy';
|
|
||||||
// Input and blur events, as in a real interaction, cause the form to be touched and
|
|
||||||
// dirtied.
|
|
||||||
dispatchEvent(loginInput, 'input');
|
|
||||||
dispatchEvent(loginInput, 'blur');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(loginInput)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(groupEl)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(formEl)).not.toContain('ng-submitted');
|
|
||||||
|
|
||||||
dispatchEvent(formEl, 'submit');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(loginInput)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(groupEl)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(formEl)).toContain('ng-submitted');
|
|
||||||
|
|
||||||
dispatchEvent(formEl, 'reset');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(loginInput)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(groupEl)).not.toContain('ng-submitted');
|
|
||||||
expect(sortedClassList(formEl)).not.toContain('ng-submitted');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1636,7 +1501,7 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]');
|
|||||||
|
|
||||||
|
|
||||||
it('should allow child control updateOn blur to override group updateOn', () => {
|
it('should allow child control updateOn blur to override group updateOn', () => {
|
||||||
const fixture = initTest(NestedFormGroupNameComp);
|
const fixture = initTest(NestedFormGroupComp);
|
||||||
const loginControl =
|
const loginControl =
|
||||||
new FormControl('', {validators: Validators.required, updateOn: 'change'});
|
new FormControl('', {validators: Validators.required, updateOn: 'change'});
|
||||||
const passwordControl = new FormControl('', Validators.required);
|
const passwordControl = new FormControl('', Validators.required);
|
||||||
@ -1945,7 +1810,7 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]');
|
|||||||
const validatorSpy = jasmine.createSpy('validator');
|
const validatorSpy = jasmine.createSpy('validator');
|
||||||
const groupValidatorSpy = jasmine.createSpy('groupValidatorSpy');
|
const groupValidatorSpy = jasmine.createSpy('groupValidatorSpy');
|
||||||
|
|
||||||
const fixture = initTest(NestedFormGroupNameComp);
|
const fixture = initTest(NestedFormGroupComp);
|
||||||
const formGroup = new FormGroup({
|
const formGroup = new FormGroup({
|
||||||
signin: new FormGroup({login: new FormControl(), password: new FormControl()}),
|
signin: new FormGroup({login: new FormControl(), password: new FormControl()}),
|
||||||
email: new FormControl('', {updateOn: 'submit'})
|
email: new FormControl('', {updateOn: 'submit'})
|
||||||
@ -2042,7 +1907,7 @@ const ValueAccessorB = createControlValueAccessor('[cva-b]');
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should allow child control updateOn submit to override group updateOn', () => {
|
it('should allow child control updateOn submit to override group updateOn', () => {
|
||||||
const fixture = initTest(NestedFormGroupNameComp);
|
const fixture = initTest(NestedFormGroupComp);
|
||||||
const loginControl =
|
const loginControl =
|
||||||
new FormControl('', {validators: Validators.required, updateOn: 'change'});
|
new FormControl('', {validators: Validators.required, updateOn: 'change'});
|
||||||
const passwordControl = new FormControl('', Validators.required);
|
const passwordControl = new FormControl('', Validators.required);
|
||||||
@ -4942,7 +4807,7 @@ class FormGroupComp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'nested-form-group-name-comp',
|
selector: 'nested-form-group-comp',
|
||||||
template: `
|
template: `
|
||||||
<form [formGroup]="form">
|
<form [formGroup]="form">
|
||||||
<div formGroupName="signin" login-is-empty-validator>
|
<div formGroupName="signin" login-is-empty-validator>
|
||||||
@ -4952,7 +4817,7 @@ class FormGroupComp {
|
|||||||
<input *ngIf="form.contains('email')" formControlName="email">
|
<input *ngIf="form.contains('email')" formControlName="email">
|
||||||
</form>`
|
</form>`
|
||||||
})
|
})
|
||||||
class NestedFormGroupNameComp {
|
class NestedFormGroupComp {
|
||||||
// TODO(issue/24571): remove '!'.
|
// TODO(issue/24571): remove '!'.
|
||||||
form!: FormGroup;
|
form!: FormGroup;
|
||||||
}
|
}
|
||||||
@ -4975,20 +4840,6 @@ class FormArrayComp {
|
|||||||
cityArray!: FormArray;
|
cityArray!: FormArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'nested-form-array-name-comp',
|
|
||||||
template: `
|
|
||||||
<form [formGroup]="form">
|
|
||||||
<div formArrayName="arr">
|
|
||||||
<input formControlName="0">
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
`
|
|
||||||
})
|
|
||||||
class NestedFormArrayNameComp {
|
|
||||||
form!: FormGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'form-array-nested-group',
|
selector: 'form-array-nested-group',
|
||||||
template: `
|
template: `
|
||||||
|
@ -187,21 +187,6 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat
|
|||||||
dispatchEvent(input, 'input');
|
dispatchEvent(input, 'input');
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
|
expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
|
||||||
|
|
||||||
const formEl = fixture.debugElement.query(By.css('form')).nativeElement;
|
|
||||||
dispatchEvent(formEl, 'submit');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(formEl)).toEqual([
|
|
||||||
'ng-dirty', 'ng-submitted', 'ng-touched', 'ng-valid'
|
|
||||||
]);
|
|
||||||
expect(sortedClassList(input)).not.toContain('ng-submitted');
|
|
||||||
|
|
||||||
dispatchEvent(formEl, 'reset');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(formEl)).toEqual(['ng-pristine', 'ng-untouched', 'ng-valid']);
|
|
||||||
expect(sortedClassList(input)).not.toContain('ng-submitted');
|
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -259,52 +244,9 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat
|
|||||||
|
|
||||||
expect(sortedClassList(modelGroup)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
|
expect(sortedClassList(modelGroup)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
|
||||||
expect(sortedClassList(form)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
|
expect(sortedClassList(form)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
|
||||||
|
|
||||||
const formEl = fixture.debugElement.query(By.css('form')).nativeElement;
|
|
||||||
dispatchEvent(formEl, 'submit');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(formEl)).toEqual([
|
|
||||||
'ng-dirty', 'ng-submitted', 'ng-touched', 'ng-valid'
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should set status classes involving nested FormGroups', () => {
|
|
||||||
const fixture = initTest(NgModelNestedForm);
|
|
||||||
fixture.componentInstance.first = '';
|
|
||||||
fixture.componentInstance.other = '';
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(sortedClassList(modelGroup)).toEqual(['ng-pristine', 'ng-untouched', 'ng-valid']);
|
|
||||||
|
|
||||||
expect(sortedClassList(form)).toEqual(['ng-pristine', 'ng-untouched', 'ng-valid']);
|
|
||||||
|
|
||||||
const formEl = fixture.debugElement.query(By.css('form')).nativeElement;
|
|
||||||
dispatchEvent(formEl, 'submit');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(modelGroup)).toEqual(['ng-pristine', 'ng-untouched', 'ng-valid']);
|
|
||||||
expect(sortedClassList(form)).toEqual([
|
|
||||||
'ng-pristine', 'ng-submitted', 'ng-untouched', 'ng-valid'
|
|
||||||
]);
|
|
||||||
expect(sortedClassList(input)).not.toContain('ng-submitted');
|
|
||||||
|
|
||||||
dispatchEvent(formEl, 'reset');
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
expect(sortedClassList(modelGroup)).toEqual(['ng-pristine', 'ng-untouched', 'ng-valid']);
|
|
||||||
expect(sortedClassList(form)).toEqual(['ng-pristine', 'ng-untouched', 'ng-valid']);
|
|
||||||
expect(sortedClassList(input)).not.toContain('ng-submitted');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not create a template-driven form when ngNoForm is used', () => {
|
it('should not create a template-driven form when ngNoForm is used', () => {
|
||||||
const fixture = initTest(NgNoFormComp);
|
const fixture = initTest(NgNoFormComp);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@ -2425,24 +2367,6 @@ class NgModelNgIfForm {
|
|||||||
email!: string;
|
email!: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'ng-model-nested',
|
|
||||||
template: `
|
|
||||||
<form>
|
|
||||||
<div ngModelGroup="contact-info">
|
|
||||||
<input name="first" [(ngModel)]="first">
|
|
||||||
<div ngModelGroup="other-names">
|
|
||||||
<input name="other-names" [(ngModel)]="other">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
`
|
|
||||||
})
|
|
||||||
class NgModelNestedForm {
|
|
||||||
first!: string;
|
|
||||||
other!: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ng-no-form',
|
selector: 'ng-no-form',
|
||||||
template: `
|
template: `
|
||||||
|
Loading…
x
Reference in New Issue
Block a user