Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: ion-picker moving by its own when emulated in tablet #30299

Open
3 tasks done
MikelMoli opened this issue Mar 24, 2025 · 1 comment
Open
3 tasks done

bug: ion-picker moving by its own when emulated in tablet #30299

MikelMoli opened this issue Mar 24, 2025 · 1 comment
Labels

Comments

@MikelMoli
Copy link

MikelMoli commented Mar 24, 2025

Prerequisites

Current Behavior

When using ion-picker component to let the user choose how much time will a timer run, the ion-picker moves by its own and doesn't stay in the column option that the user has set. This happens only in tablets simulators in the browser (I don't have a tablet my own to test this).

This has been tested in Chrome and Mozilla. It doesn't seem to be an Apple thing, as in the iPhone devices it works properly.

In Mobile - iPhone 12 pro (it works OK in other mobile devices too)

Image

In tablet - iPad Pro (it happens in all the tablets)

Image

Expected Behavior

Ion-picker column does not change its values by its own in tablets as it does in mobile devices.

Steps to Reproduce

  1. Create the next HTML and TS file:

This is my component HTML:

<ion-picker class="custom-picker">
  <ion-picker-column 
    [value]="selectedHour" 
    (ionChange)="hourChanged($event)">
    <ion-picker-column-option *ngFor="let num of hourOptions" [value]="num">{{ num }}</ion-picker-column-option>
  </ion-picker-column>
  <ion-picker-column 
    [value]="selectedMinute" 
    (ionChange)="minuteChanged($event)">
    <div class="two-dots" slot="prefix">:</div>
    <ion-picker-column-option *ngFor="let num of secMinOptions" [value]="num">{{ num }}</ion-picker-column-option>
    <div class="two-dots" slot="suffix">:</div>
  </ion-picker-column>
  <ion-picker-column 
    [value]="selectedSecond" 
    (ionChange)="secondChanged($event)">
    <ion-picker-column-option *ngFor="let num of secMinOptions" [value]="num">{{ num }}</ion-picker-column-option>
  </ion-picker-column>
</ion-picker>

This is my TS file:

import { CommonModule } from '@angular/common';
import { AfterViewInit, Component, ElementRef, EventEmitter, Output, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { IonicModule, IonPicker } from '@ionic/angular';

@Component({
  selector: 'app-custom-class-length',
  standalone: true,
  imports: [IonicModule, FormsModule, CommonModule],
  templateUrl: './custom-class-length.component.html',
  styleUrls: ['./custom-class-length.component.scss'],
})
export class CustomClassLengthComponent implements AfterViewInit {
  @Output() timeChanged = new EventEmitter<string>();
  selectedHour: string = '00';
  selectedMinute: string = '00';
  selectedSecond: string = '30';
  hourOptions = Array.from({ length: 24 }, (_, i) => i.toString().padStart(2, '0'));
  secMinOptions = Array.from({ length: 60 }, (_, i) => i.toString().padStart(2, '0'));

  constructor() {}

  ngAfterViewInit(): void {
    setTimeout(() => {
      const picker = document.querySelector('ion-picker.custom-picker');
      if (picker && picker.shadowRoot) {
        const beforeEl = picker.shadowRoot.querySelector('.picker-before') as HTMLElement;
        const afterEl = picker.shadowRoot.querySelector('.picker-after') as HTMLElement;
    
        if (beforeEl) beforeEl.style.background = 'transparent';
        if (afterEl) afterEl.style.background = 'transparent';
      }

      const pickerOptions = document.querySelectorAll('ion-picker-column-option');

      pickerOptions.forEach((option) => {
        const shadowButton = option.shadowRoot?.querySelector('button');
        
        if (shadowButton) {
          shadowButton.style.height = '100%';
          shadowButton.style.lineHeight = 'unset';
        }
      });
    }, 100);
  }

  getSelectedTime() {
    return 
  }

  hourChanged(event: CustomEvent) {
    this.selectedHour = event.detail.value;
    this.emitTime();
  }

  minuteChanged(event: CustomEvent) {
    this.selectedMinute = event.detail.value;
    this.emitTime();
  }

  secondChanged(event: CustomEvent) {
    this.selectedSecond = event.detail.value;
    this.emitTime();
  }

  private emitTime() {
    let timeValue = `${this.selectedHour}:${this.selectedMinute}:${this.selectedSecond}`
    console.log(timeValue)
    this.timeChanged.emit(timeValue);
  }
}
  1. Run Ionic serve in Mozilla or Chrome
  2. Select device view and choose iPad Pro or any tablet
  3. Change the selected option

Ionic Info

Versions:
Ionic:

Ionic CLI : 7.2.0
Ionic Framework : @ionic/angular 8.5.0
@angular-devkit/build-angular : 18.2.15
@angular-devkit/schematics : 18.2.15
@angular/cli : 18.2.15
@ionic/angular-toolkit : 11.0.1

Capacitor:

Capacitor CLI : 7.1.0
@capacitor/android : 7.0.1
@capacitor/core : 7.1.0
@capacitor/ios : 7.0.1

Utility:

cordova-res : 0.15.4
native-run : 2.0.1

System:

NodeJS : v22.12.0
npm : 10.9.0
OS : Linux 5.15

Additional Information

No response

@MikelMoli
Copy link
Author

Just in case someone need a workaround...

This can be fixed by changing the font-size of the component ion-picker-column-option. It seems like if the font size is too big, the wheel spins to the top values and if the font size is too small it spins to the values on the bottom. So the only way I found that it doesn't spin and stays in the selected values is to pick a font that is not too big nor too small.

The problem here is that you will need to set different font-sizes for different media devices, and even like that the widget might not good look when is functioning OK.

This issue seems to be related with this one: #29713

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant