how to make ion-datetime's display the picker in a modal or bottom page slider instead of directly display it

Viewed 2885

I'm doing an ionic project using Ionic 6 and I need a datetime field in my form.

<ion-content>
  <ion-grid>
    <ion-row>
      <ion-col>
        <ion-item>
          <ion-label>Available From</ion-label>
          <ion-datetime min="1994-03-14" max="2012-12-09" value="2008-09-02"></ion-datetime>
        </ion-item>
      </ion-col>
    </ion-row>
  </ion-grid>
</ion-content>

From what I have searched in many sources, it seems like the correct behavior should be button which is when it is clicked will display a slider up from the bottom of the page. The selector displays scrollable columns that can be used to individually specify values for years, months, days, hours, and minutes.

Instead of that, what I get is the picker is displayed instead of button or anything.

enter image description here

Am I missing something? I tried all usage example in the documentation and all of them are displayed like that. Please help.

4 Answers

It's still possible by using ion-popover.

<ion-item>
    <ion-label position="stacked">Date of birth</ion-label>
    <ion-input value="{{ user.birthDate | date: 'dd MMM yyyy' }}" id="date"></ion-input>
    <ion-popover trigger="date" >
        <ng-template>
            <ion-datetime presentation="date" [(ngModel)]="user.birthDate" locale="en-US"></ion-datetime>
        </ng-template>
    </ion-popover>
</ion-item>

Example

All credit to Damir Arh who posted the solution here: https://www.damirscorner.com/blog/posts/20220107-DatePickerPopupInIonic6.html

The ion-datetime has changed in Ionic v6. To have a text field displaying the date in your form and have the calendar picker in a popup, use it like in the following example (startdate is the date variable):

<ion-row>
   <ion-col>Date:</ion-col>
   <ion-col id="open-date-input" class="ion-text-end" style="margin-right: 10px;">
     <ion-text>{{ startdate|date:'shortDate':undefined:this.translate.currentLang }}</ion-text>
   </ion-col>
   <ion-popover trigger="open-date-input" show-backdrop="false">
     <ng-template>
       <ion-datetime
          #popoverDate
          value="{{startdate}}"
          presentation="date"
          showDefaultButtons=true
          (ionChange)="startdate = popoverDate.value"
        ></ion-datetime>
     </ng-template>
   </ion-popover>          
</ion-row>

Of course you may omit/replace the date formatting pipe in the ion-text to your needs.

I'm using ionic with react and styled components and below I extracted from my code base the solution using an IonModal.

import React, {useState} from "react";
import styled from "styled-components";
import {IonDatetime, IonIcon, IonModal} from "@ionic/react";
import {caretDown, caretDownOutline} from "ionicons/icons";

const IonModalBox = styled(IonModal)`
      --height: '45%';
      &::part(content){
        position: absolute;
        bottom: 0;
      }
`

const DateTimePickerContainer = styled.div`
    display: flex;
    flex-direction: row;
    align-content: center;
    width: 100%;
`

const ValueContainer = styled.div`
    flex-grow: 1;
`

interface DateTimePickerComponentProps {
    value: string | null;
}

export const DateTimePickerComponent: React.FC<DateTimePickerComponentProps> = (props) => {
    const [value, setValue] = useState<string | null>(props.value);
    const [showDialog, setShowDialog] = useState(false);

    const onClickHandler = () => {
        setShowDialog(true);
    }
    const onIonChangeHandler = (value: string | null) => {
        setValue(value);
        setShowDialog(false);
    }

    return (
        <>
            <DateTimePickerContainer onClick={onClickHandler}>
                <ValueContainer>{value}</ValueContainer>
                <IonIcon md={caretDown} ios={caretDownOutline}/>
            </DateTimePickerContainer>
            <IonModalBox isOpen={showDialog} onDidDismiss={() => setShowDialog(false)}>
                <IonDatetime value={value}
                             onIonChange={e => onIonChangeHandler(e.detail.value || null)}
                             size={"cover"}
                             showDefaultButtons={true}/>
            </IonModalBox>
        </>

    )
}

Since v6 you can (and should) use datetime-button with either ion-modal or ion-popover:

<ion-datetime-button datetime="datetime"></ion-datetime-button>
<ion-modal [keepContentsMounted]="true">
  <ng-template>
    <ion-datetime id="datetime"></ion-datetime>
  </ng-template>
</ion-modal>

Upd: And if you need wheel-style pickers use prefer-wheel attribute.

Source: Ionic UI Components → Datetime Button

Related