Skip to content

Commit d0cad6b

Browse files
authored
fix(input): mark ion-input touched on blur instead of changed (#12812)
fixes #12102
1 parent f5ef1ca commit d0cad6b

File tree

4 files changed

+28
-9
lines changed

4 files changed

+28
-9
lines changed

src/components/checkbox/checkbox.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ export class Checkbox extends BaseInput<boolean> implements IonicTapInput, OnDes
126126
ev.preventDefault();
127127
ev.stopPropagation();
128128
this.value = !this.value;
129+
this._fireTouched();
129130
}
130131

131132
/**
@@ -141,5 +142,4 @@ export class Checkbox extends BaseInput<boolean> implements IonicTapInput, OnDes
141142
_inputUpdated() {
142143
this._item && this._item.setElementClass('item-checkbox-checked', this._value);
143144
}
144-
145145
}

src/components/segment/segment.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ export class Segment extends BaseInput<string> implements AfterContentInit {
9090
ngAfterContentInit() {
9191
this._initialize();
9292
this._buttons.forEach(button => {
93-
button.ionSelect.subscribe((selectedButton: any) => this.value = selectedButton.value);
93+
button.ionSelect.subscribe((selectedButton: any) => {
94+
this.value = selectedButton.value;
95+
this._fireTouched();
96+
});
9497
});
9598
}
9699

@@ -109,6 +112,4 @@ export class Segment extends BaseInput<string> implements AfterContentInit {
109112
button.isActive = (button.value === value);
110113
}
111114
}
112-
113-
114115
}

src/util/base-input.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { AfterContentInit, ElementRef, EventEmitter, Input, NgZone, Output, Rend
22
import { ControlValueAccessor } from '@angular/forms';
33
import { NgControl } from '@angular/forms';
44

5-
import { assert, deepCopy, isArray, isPresent, isString, isTrueProperty, isUndefined } from './util';
5+
import { assert, deepCopy, isArray, isPresent, isString, isTrueProperty, isUndefined } from './util';
66
import { IonicFormInput } from './form';
77
import { Ion } from '../components/ion';
88
import { Config } from '../config/config';
@@ -228,9 +228,17 @@ export class BaseInput<T> extends Ion implements CommonInput<T> {
228228

229229
this._form && this._form.unsetAsFocused(this);
230230
this._setFocus(false);
231+
this._fireTouched();
231232
this.ionBlur.emit(this);
232233
}
233234

235+
/**
236+
* @hidden
237+
*/
238+
_fireTouched() {
239+
this._onTouched && this._onTouched();
240+
}
241+
234242
/**
235243
* @hidden
236244
*/
@@ -253,7 +261,6 @@ export class BaseInput<T> extends Ion implements CommonInput<T> {
253261
*/
254262
private onChange() {
255263
this._onChanged && this._onChanged(this._inputNgModelEvent());
256-
this._onTouched && this._onTouched();
257264
}
258265

259266
/**

src/util/input-tester.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ function testState<T>(input: BaseInput<T>, config: TestConfig, isInit: boolean)
107107
if (isInit) {
108108
let blurCount = 0;
109109
let focusCount = 0;
110+
let onTouchedCalled = 0;
110111
const subBlur = input.ionBlur.subscribe((ev: any) => {
111112
assertEqual(ev, input, 'ionBlur argument is wrong');
112113
blurCount++;
@@ -121,6 +122,15 @@ function testState<T>(input: BaseInput<T>, config: TestConfig, isInit: boolean)
121122
assert(false, 'onFocusChange test failed');
122123
}
123124
});
125+
input.registerOnTouched(() => {
126+
assertEqual(onTouchedCalled, 0, 'registerOnTouched: internal error');
127+
onTouchedCalled++;
128+
});
129+
130+
input._fireBlur();
131+
assertEqual(blurCount, 0, 'blur should not have been emitted');
132+
assertEqual(onTouchedCalled, 0, 'touched should not have been called');
133+
124134
input._fireFocus();
125135
assertEqual(input._isFocus, true, 'should be focus');
126136
assertEqual(input.isFocus(), true, 'should be focus');
@@ -129,6 +139,7 @@ function testState<T>(input: BaseInput<T>, config: TestConfig, isInit: boolean)
129139
input._fireBlur();
130140
assertEqual(input._isFocus, false, 'should be not focus');
131141
assertEqual(input.isFocus(), false, 'should be not focus');
142+
assertEqual(onTouchedCalled, 1, 'touched should have been called');
132143
input._fireBlur(); // it should not crash
133144

134145
assertEqual(focusCount, 1, 'ionFocus was not called correctly');
@@ -166,7 +177,7 @@ function testWriteValue<T>(input: BaseInput<T>, config: TestConfig, isInit: bool
166177
OnChangeCalled++;
167178
});
168179

169-
// Test registerOnChange
180+
// Test registerOnTouched
170181
input.registerOnTouched(() => {
171182
assertEqual(OnTouchedCalled, 0, 'registerOnTouched: internal error');
172183

@@ -187,7 +198,7 @@ function testWriteValue<T>(input: BaseInput<T>, config: TestConfig, isInit: bool
187198
assertEqual(ionChangeCalled, 0, 'loop: ionChange error');
188199
}
189200
assertEqual(OnChangeCalled, 1, 'loop: OnChangeCalled was not called');
190-
assertEqual(OnTouchedCalled, 1, 'loop: OnTouchedCalled was not called');
201+
assertEqual(OnTouchedCalled, 0, 'loop: OnTouchedCalled was called');
191202

192203
OnTouchedCalled = OnChangeCalled = ionChangeCalled = 0;
193204

@@ -212,7 +223,7 @@ function testWriteValue<T>(input: BaseInput<T>, config: TestConfig, isInit: bool
212223
input.value = null;
213224
assertEqual(input.value, config.defaultValue, 'null: wrong default value');
214225
assertEqual(OnChangeCalled, 1, 'null: OnChangeCalled was not called');
215-
assertEqual(OnTouchedCalled, 1, 'null: OnTouchedCalled was not called');
226+
assertEqual(OnTouchedCalled, 0, 'null: OnTouchedCalled was called');
216227

217228

218229
input.registerOnChange(null);

0 commit comments

Comments
 (0)