ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
51.02k stars 13.51k forks source link

bug: wheel date-picker and modal does not set value in real-time when spinning the date picker #26129

Closed BurkusCat closed 1 year ago

BurkusCat commented 2 years ago

Prerequisites

Ionic Framework Version

Current Behavior

When using the wheel-picker in a modal, if you spin one of the date component columns rapidly and you press 'DONE' before it finishes spinning it won't save any new value. Based on how other apps work (e.g. Samsung Alarms), this isn't the behaviour I would expect and it could lead to the user entering in data and losing it.

Example: If I start the date picker on this date image

...and I spin the year rapidly to go forward in time image

... if I press "DONE" while it is still spinning it will not update [(ngModel)] with any new value. The date value set will still remain as 14th October 2002.

Expected Behavior

I'm not 100% sure what the best solution to this issue is. Should it be that when you press "DONE" it will save the value that it has currently spun to in the window? Should it wait or calculate where the spin will land and save that value?

Steps to Reproduce

<ion-input (click)="openModal()"
    id="datetime-modal"
    readonly="true"
    value="{{ getFormattedDateDisplay(dateValue) }}"></ion-input>

<ion-modal [isOpen]="isModalOpen"
    (ionModalDidDismiss)="handleDismiss()">
    <ng-template>
        <ion-datetime
            presentation="date"
            [preferWheel]="true"
            showDefaultButtons="true"
            [(ngModel)]="dateValue"></ion-datetime>
    </ng-template>
</ion-modal>
@Component({
    selector: 'test-date-picker',
    templateUrl: './test-date-picker.component.html',
    styleUrls: ['./test-date-picker.component.scss'],
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => TestDatePickerComponent),
            multi: true,
        },
    ],
})
export class TestDatePickerComponent implements ControlValueAccessor {
    @ViewChild(IonModal) modal: IonModal;

    /**
    * How the date should be displayed on the page. Default 'DD/MM/YYYY'
    */
    @Input() public displayFormat: string = 'DD/MM/YYYY';

    /**
    * The value of the component
    */
    @Input() public date: string;

    public isModalOpen = false;
    public onTouched: () => void;
    public propagateChange: (_: any) => void;

    constructor(
        public datePicker: DatePicker,
        public logger: LogService,
        public platform: Platform,
    ) { }

    public get dateValue() {
        return this.date;
    }

    public set dateValue(val: string) {
            this.date = moment(val).format('YYYY-MM-DD');

        this.propagateChange(this.date);
    }

    public writeValue(value: any) {
        if (value !== undefined) {
            this.date = value;
        }
    }

    public registerOnChange(fn) {
        this.propagateChange = fn;
    }

    public registerOnTouched(fn) {
        this.onTouched = fn;
    }

    public openModal() {
        this.isModalOpen = true;
    }

    public handleDismiss() {
        this.isModalOpen = false;
    }

    /**
     * Returns a string formatted in the component's display format
     *
     * @param date the date to format
     */
    public getFormattedDateDisplay(date: string): string {
        if (!date) {
            return '';
        }

        return moment(date).format(this.displayFormat);
    }
}

Code Reproduction URL

No response

Ionic Info

Ionic:

Ionic CLI : 6.19.0 (C:\Users\burku\AppData\Roaming\npm\node_modules\@ionic\cli) Ionic Framework : @ionic/angular 6.3.0 @angular-devkit/build-angular : 13.3.9 @angular-devkit/schematics : 13.2.6 @angular/cli : 13.2.6 @ionic/angular-toolkit : 6.1.0

Capacitor:

Capacitor CLI : 3.5.1 @capacitor/android : 4.3.0 @capacitor/core : 4.3.0 @capacitor/ios : not installed

Utility:

cordova-res : not installed globally native-run : 1.7.1

System:

NodeJS : v16.15.0 (C:\Program Files\nodejs\node.exe) npm : 8.5.5 OS : Windows 10

Additional Information

No response

liamdebeasi commented 2 years ago

Thanks for the report. The wheel picker in Ionic does not update the value until scrolling has come to a stop. This was designed to model the wheel picker on iOS:

https://user-images.githubusercontent.com/2721089/195861584-13ac140d-7d52-4108-bd33-e8db38fce8e9.mp4

In the video above, the time is not updated to to "12:00" until scrolling has stopped.

BurkusCat commented 2 years ago

Thanks @liamdebeasi , in the video, the "Add" button at the top-right is disabled while the wheel is still spinning. Is it possible to replicate this behaviour with the Ionic wheel picker modal by disabling the "DONE" button while the wheel is spinning? (this may be something I code in my project rather than being in Ionic itself). Is there any way I can tell that the Ionic wheel picker is spinning to do this?

liamdebeasi commented 2 years ago

You can replicate the iOS behavior, but we do not expose a way to tell if the picker is spinning.

To replicate the iOS behavior, you could have an <ion-button> that is disabled initially. Once ionChange fires from ion-datetime you can enable the button. Note that on iOS, the "Add" button does not get disabled if the user starts to spin the wheel again. The disabled state only ensures that the datepicker has a value.

ionitron-bot[bot] commented 1 year ago

Thanks for the issue! This issue is being closed due to the lack of a reply. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

Thank you for using Ionic!