Skip to content

Commit d10c6dd

Browse files
committed
fix: fix bug that caused control state value to not be properly set to form element if the ID of the control state changed but the state's value was the same as the last value the view reported for the previous state
1 parent 8f91ea7 commit d10c6dd

File tree

3 files changed

+40
-4
lines changed

3 files changed

+40
-4
lines changed

CHANGELOG.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
## Ngrx Forms Changelog
22

3-
<a name="August 19, 2017"></a>
4-
### August 19, 2017
5-
* Create library
3+
<a name="1.0.1"></a>
4+
### 1.0.1
5+
6+
#### Bugfixes
7+
8+
* fix bug that caused control state value to not be properly set to form element if the ID of the control state changed but the state's value was the same as the last value the view reported for the previous state
9+
10+
<a name="1.0.0"></a>
11+
### 1.0.0
12+
* Initial version of the library

src/control/directive.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,28 @@ describe(NgrxFormControlDirective.name, () => {
6464
expect(spy).not.toHaveBeenCalled();
6565
});
6666

67+
it('should write the value when the state value does not change but the id does', () => {
68+
const spy = spyOn(valueAccessor, 'writeValue');
69+
directive.ngrxFormControlState = { ...INITIAL_STATE, id: FORM_CONTROL_ID + '1' };
70+
expect(spy).toHaveBeenCalledWith(INITIAL_STATE.value);
71+
});
72+
73+
it('should write the value when the state value does not change but the id does after a new view value was reported', () => {
74+
const newValue = 'new value';
75+
onChange(newValue);
76+
const spy = spyOn(valueAccessor, 'writeValue');
77+
directive.ngrxFormControlState = { ...INITIAL_STATE, id: FORM_CONTROL_ID + '1', value: newValue };
78+
expect(spy).toHaveBeenCalledWith(newValue);
79+
});
80+
81+
it('should write the value when the state value does not change but the id does after an undefined view value was reported', () => {
82+
const newValue = undefined as any;
83+
onChange(newValue);
84+
const spy = spyOn(valueAccessor, 'writeValue');
85+
directive.ngrxFormControlState = { ...INITIAL_STATE, id: FORM_CONTROL_ID + '1', value: newValue };
86+
expect(spy).toHaveBeenCalledWith(newValue);
87+
});
88+
6789
it('should dispatch an action if the view value changes', done => {
6890
const newValue = 'new value';
6991
onChange(newValue);

src/control/directive.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ export class NgrxFormControlDirective<TValue extends FormControlValueTypes> impl
3838
throw new Error('The control state must not be undefined!');
3939
}
4040

41+
if (this.state && newState.id !== this.state.id) {
42+
this.valueWasReported = false;
43+
this.lastReportedViewValue = undefined as any;
44+
}
45+
4146
this.state = newState;
4247
this.stateSubject$.next(newState);
4348
}
@@ -67,6 +72,7 @@ export class NgrxFormControlDirective<TValue extends FormControlValueTypes> impl
6772
// types something the cursor is forced to the end of the input; to prevent this
6873
// behavior we compare the last reported value with the value to be set and filter out
6974
// those values that are equal to the last reported value
75+
private valueWasReported: boolean;
7076
private lastReportedViewValue: TValue;
7177

7278
constructor(
@@ -89,6 +95,7 @@ export class NgrxFormControlDirective<TValue extends FormControlValueTypes> impl
8995
this.valueAccessor.registerOnChange((newValue: TValue) => {
9096
newValue = this.convertViewValue(newValue);
9197
if (newValue !== this.state.value) {
98+
this.valueWasReported = true;
9299
this.lastReportedViewValue = newValue;
93100
this.actionsSubject.next(new SetValueAction(this.state.id, newValue));
94101
}
@@ -105,7 +112,7 @@ export class NgrxFormControlDirective<TValue extends FormControlValueTypes> impl
105112
.map(s => ({ id: s.id, value: this.convertModelValue(s.value) }))
106113
.distinctUntilChanged((l, r) => l.id === r.id && l.value === r.value)
107114
.map(s => s.value)
108-
.filter(v => v !== this.lastReportedViewValue)
115+
.filter(v => !this.valueWasReported || v !== this.lastReportedViewValue)
109116
.subscribe(value => this.valueAccessor.writeValue(value))
110117
);
111118

0 commit comments

Comments
 (0)