8000 fix(angular,vue): range form value updates while dragging knob (#28422) · ionic-team/ionic-framework@0854a11 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0854a11

Browse files
fix(angular,vue): range form value updates while dragging knob (#28422)
Issue number: Resolves #28256 --------- <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? <!-- Please describe the current behavior that you are modifying. --> In the form integrations for Angular and Vue, the value of a range does not update while the knob is actively being dragged, only when the knob is released. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> The form integrations now update the range's value when the `ionInput` event fires, rather than `ionChange`. ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change, please describe the impact and migration path for existing applications below. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> I wasn't sure how to add reliable automated tests for this behavior. The difference only applies when actively dragging the knob, and we've had issues with such gestures being flaky in the past. I did add value displays to the test apps so the behavior can be manually tested.
1 parent 60630cc commit 0854a11

File tree

9 files changed

+73
-14
lines changed

9 files changed

+73
-14
lines changed

core/stencil.config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,13 +201,13 @@ export const config: Config = {
201201
externalEvent: 'ionChange'
202202
},
203203
{
204-
elements: ['ion-datetime', 'ion-radio-group', 'ion-radio', 'ion-range', 'ion-segment', 'ion-segment-button', 'ion-select', 'ion-accordion-group'],
204+
elements: ['ion-datetime', 'ion-radio-group', 'ion-radio', 'ion-segment', 'ion-segment-button', 'ion-select', 'ion-accordion-group'],
205205
targetAttr: 'value',
206206
event: 'v-ion-change',
207207
externalEvent: 'ionChange'
208208
},
209209
{
210-
elements: ['ion-input', 'ion-searchbar', 'ion-textarea'],
210+
elements: ['ion-input', 'ion-searchbar', 'ion-textarea', 'ion-range'],
211211
targetAttr: 'value',
212212
event: 'v-ion-input',
213213
externalEvent: 'ionInput'

packages/angular/src/directives/control-value-accessors/select-value-accessor.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ValueAccessor } from '@ionic/angular/common';
44

55
@Directive({
66
/* tslint:disable-next-line:directive-selector */
7-
selector: 'ion-range, ion-select, ion-radio-group, ion-segment, ion-datetime',
7+
selector: 'ion-select, ion-radio-group, ion-segment, ion-datetime',
88
providers: [
99
{
1010
provide: NG_VALUE_ACCESSOR,
@@ -20,12 +20,7 @@ export class SelectValueAccessorDirective extends ValueAccessor {
2020

2121
@HostListener('ionChange', ['$event.target'])
2222
_handleChangeEvent(
23-
el:
24-
| HTMLIonRangeElement
25-
| HTMLIonSelectElement
26-
| HTMLIonRadioGroupElement
27-
| HTMLIonSegmentElement
28-
| HTMLIonDatetimeElement
23+
el: HTMLIonSelectElement | HTMLIonRadioGroupElement | HTMLIonSegmentElement | HTMLIonDatetimeElement
2924
): void {
3025
this.handleValueChange(el, el.value);
3126
}

packages/angular/src/directives/control-value-accessors/text-value-accessor.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import { ElementRef, Injector, Directive, HostListener } from '@angular/core';
22
import { NG_VALUE_ACCESSOR } from '@angular/forms';
33
import { ValueAccessor } from '@ionic/angular/common';
44

5+
// TODO(FW-5495): rename class since range isn't a text component
56
@Directive({
6-
selector: 'ion-input:not([type=number]),ion-textarea,ion-searchbar',
7+
selector: 'ion-input:not([type=number]),ion-textarea,ion-searchbar,ion-range',
78
providers: [
89
{
910
provide: NG_VALUE_ACCESSOR,
@@ -18,7 +19,9 @@ export class TextValueAccessorDirective extends ValueAccessor {
1819
}
1920

2021
@HostListener('ionInput', ['$event.target'])
21-
_handleInputEvent(el: HTMLIonInputElement | HTMLIonTextareaElement | HTMLIonSearchbarElement): void {
22+
_handleInputEvent(
23+
el: HTMLIonInputElement | HTMLIonTextareaElement | HTMLIonSearchbarElement | HTMLIonRangeElement
24+
): void {
2225
this.handleValueChange(el, el.value);
2326
}
2427
}

packages/angular/standalone/src/directives/range.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ export class IonRange extends ValueAccessor implements OnInit {
8888
proxyInputs(IonRange, RANGE_INPUTS);
8989
}
9090

91-
@HostListener('ionChange', ['$event.target'])
92-
handleIonChange(el: HTMLIonRangeElement): void {
91+
@HostListener('ionInput', ['$event.target'])
92+
handleIonInput(el: HTMLIonRangeElement): void {
9393
this.handleValueChange(el, el.value);
9494
}
9595
}

packages/angular/test/base/src/app/lazy/form-controls/range/range.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<div slot="label">Range</div>
1212
</ion-range>
1313
</ion-item>
14+
<p>Value: {{ form.controls['range'].value }}</p>
1415
</ion-list>
1516
<ion-button type="submit">Submit</ion-button>
1617
</form>

packages/vue/src/proxies.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ export const IonRange = /*@__PURE__*/ defineContainer<JSX.IonRange, JSX.IonRange
630630
'ionKnobMoveStart',
631631
'ionKnobMoveEnd'
632632
],
633-
'value', 'v-ion-change', 'ionChange');
633+
'value', 'v-ion-input', 'ionInput');
634634

635635

636636
export const IonRefresher = /*@__PURE__*/ defineContainer<JSX.IonRefresher>('ion-refresher', defineIonRefresher, [

packages/vue/test/base/src/router/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ const routes: Array<RouteRecordRaw> = [
8282
path: '/components/select',
8383
component: () => import('@/views/Select.vue')
8484
},
85+
{
86+
path: '/components/range',
87+
component: () => import('@/views/Range.vue')
88+
},
8589
{
8690
path: '/nested',
8791
component: () => import('@/views/RouterOutlet.vue'),
10000

packages/vue/test/base/src/views/Components.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
<ion-item button router-link="/components/select">
99
<ion-label>Select</ion-label>
1010
</ion-item>
11+
<ion-item button router-link="/components/range">
12+
<ion-label>Range</ion-label>
13+
</ion-item>
1114
</ion-list>
1215
</ion-content>
1316
</ion-page>
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<template>
2+
<ion-page>
3+
<ion-header>
4+
<ion-toolbar>
5+
<ion-title>Range</ion-title>
6+
</ion-toolbar>
7+
</ion-header>
8+
<ion-content>
9+
<form>
10+
<ion-list>
11+
<ion-item>
12+
<ion-range :min="0" :max="20" :value="5" v-model="range">
13+
<div slot="label">Range</div>
14+
</ion-range>
15+
</ion-item>
16+
<p>Value: {{ range }}</p>
17+
</ion-list>
18+
</form>
19+
</ion-content>
20+
</ion-page>
21+
</template>
22+
23+
<script lang="ts">
24+
import {
25+
IonPage,
26+
IonHeader,
27+
IonToolbar,
28+
IonTitle,
29+
IonContent,
30+
IonList,
31+
IonItem,
32+
IonRange
33+
} from "@ionic/vue";
34+
import { defineComponent } from "vue";
35+
36+
export default defineComponent({
37+
components: {
38+
IonPage,
39+
IonHeader,
40+
IonToolbar,
41+
IonTitle,
42+
IonContent,
43+
IonList,
44+
IonItem,
45+
IonRange
46+
},
47+
data() {
48+
return {
49+
range: 5
50+
}
51+
}
52+
});
53+
</script>

0 commit comments

Comments
 (0)
0