Skip to content

Commit

Permalink
fix(forms): Don't send updates for same value
Browse files Browse the repository at this point in the history
In case an input event sends the same value to our forms, we will discard the update and consider the input hasn't change. This will prevent having duplicate values on the valueChanges event.

Fixes #43228
  • Loading branch information
JeanMeche committed May 11, 2024
1 parent 85ac2de commit a4176a2
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 9 deletions.
7 changes: 5 additions & 2 deletions packages/forms/src/directives/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,11 @@ export function cleanUpValidators(

function setUpViewChangePipeline(control: FormControl, dir: NgControl): void {
dir.valueAccessor!.registerOnChange((newValue: any) => {
control._pendingValue = newValue;
control._pendingChange = true;
if (newValue !== control.value) {
control._pendingValue = newValue;
control._pendingChange = true;
}

control._pendingDirty = true;

if (control.updateOn === 'change') updateControl(control, dir);
Expand Down
12 changes: 6 additions & 6 deletions packages/forms/test/template_integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ describe('template-driven forms integration tests', () => {
.withContext('Expected ngModelChanges not to fire if value unchanged.')
.toEqual([]);

input.value = 'Carson';
input.value = 'Not Carson !'; // changes the existing input value
dispatchEvent(input, 'input');
fixture.detectChanges();
tick();
Expand Down Expand Up @@ -1077,7 +1077,7 @@ describe('template-driven forms integration tests', () => {
.toEqual([]);

const input = fixture.debugElement.query(By.css('input')).nativeElement;
input.value = 'Carson';
input.value = 'Not Carson !'; // Changing the existing input value
dispatchEvent(input, 'input');
fixture.detectChanges();
tick();
Expand All @@ -1095,11 +1095,11 @@ describe('template-driven forms integration tests', () => {

dispatchEvent(formEl, 'submit');
fixture.detectChanges();
tick();

expect(fixture.componentInstance.events).toEqual(
['fired'],
'Expected ngModelChanges not to fire again on submit unless value changed.',
);
expect(fixture.componentInstance.events)
.withContext('Expected ngModelChanges not to fire again on submit unless value changed.')
.toEqual(['fired']);

input.value = 'Bess';
dispatchEvent(input, 'input');
Expand Down
3 changes: 2 additions & 1 deletion packages/forms/test/value_accessor_integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ describe('value accessors', () => {
comp.cities = [{'name': 'SF'}, {'name': 'NYC'}];
comp.selectedCity = null;
fixture.detectChanges();
tick();

const select = fixture.debugElement.query(By.css('select'));

Expand Down Expand Up @@ -1429,7 +1430,7 @@ class NgModelSelectForm {
@Component({
selector: 'ng-model-select-null-form',
template: `
<select [(ngModel)]="selectedCity">
<select [(ngModel)]="selectedCity" #model="ngModel">
<option *ngFor="let c of cities" [ngValue]="c"> {{c.name}} </option>
<option [ngValue]="null">Unspecified</option>
</select>
Expand Down

0 comments on commit a4176a2

Please sign in to comment.