-
-
Notifications
You must be signed in to change notification settings - Fork 817
Feat: ui.date_input
and ui.time_input
#4815
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
base: main
Are you sure you want to change the base?
Conversation
Hi @evnchn, while you're at it, would you mind also adding a DateTimeInput as mentioned here in the Quasar docs (codepen)? |
@platinops So this is my first time making a new UI element, so I'd like to take it slowly and get these two merged before working on that. Also, I don't think a combined Date and Time input would be as urgent as the pair Not only that, personal opinion, it's totally not obvious that you click the calendar icon on the left to edit the date. I'd assume if you use this in production, users are going to be confused and ring up customer support asking "how can I change the date", so I am not sure if I should endorse sub-optimal UI design in the first place. ![]() You can open a separate feature request, if you think a combined |
Hi @evnchn. See below implementation:
I could open a separate feature request / PR for this, but for a consistent API/implementation this seemed an appropriate place to discuss. from typing import Optional, Any
from nicegui import ui
from nicegui.events import Handler, ValueChangeEventArguments, GenericEventArguments
from nicegui.elements.button import Button as button
from nicegui.elements.date import Date as date
from nicegui.elements.time import Time as time
from nicegui.elements.menu import Menu as menu
from nicegui.elements.icon import Icon as icon
from nicegui.elements.mixins.disableable_element import DisableableElement
from nicegui.elements.mixins.label_element import LabelElement
from nicegui.elements.mixins.value_element import ValueElement
class DateInput(LabelElement, ValueElement, DisableableElement):
def __init__(
self,
label: Optional[str] = None,
*,
placeholder: Optional[str] = None,
value: Optional[str] = "",
on_change: Optional[Handler[ValueChangeEventArguments]] = None,
) -> None:
"""Date Input
This element extends Quasar's `QInput <https://quasar.dev/vue-components/input>`_ component with a time picker.
:param label: displayed label for the time input
:param placeholder: text to show if no time is selected
:param value: the current time value
:param on_change: callback to execute when the value changes
"""
super().__init__(
tag="q-input", label=label, value=value, on_value_change=on_change
)
if placeholder is not None:
self._props["placeholder"] = placeholder
with self.add_slot("append"):
with (
icon("event")
.on("click", lambda: self.date_menu.open())
.classes("cursor-pointer")
):
with menu() as self.date_menu:
date(mask="YYYY-MM-DD").bind_value(self)
class TimeInput(LabelElement, ValueElement, DisableableElement):
def __init__(
self,
label: Optional[str] = None,
*,
with_seconds: Optional[bool] = False,
placeholder: Optional[str] = None,
value: str = "",
on_change: Optional[Handler[ValueChangeEventArguments]] = None,
) -> None:
"""Time Input
This element extends Quasar's `QInput <https://quasar.dev/vue-components/input>`_ component with a date picker.
:param label: displayed label for the time input
:param with_seconds: include seconds in time picker
:param placeholder: text to show if no time is selected
:param value: the current time value
:param on_change: callback to execute when the value changes
"""
super().__init__(
tag="q-input", label=label, value=value, on_value_change=on_change
)
if placeholder is not None:
self._props["placeholder"] = placeholder
mask = "HH:mm"
time_picker_props = "format24h"
if with_seconds:
mask += ":ss"
time_picker_props += " with-seconds"
with self.add_slot("append"):
with (
icon("access_time")
.on("click", lambda: self.time_menu.open())
.classes("cursor-pointer")
):
with menu() as self.time_menu:
time(mask=mask).props(time_picker_props).bind_value(self)
class DateTimeInput(LabelElement, ValueElement, DisableableElement):
def __init__(
self,
label: Optional[str] = None,
*,
with_seconds: Optional[bool] = False,
placeholder: Optional[str] = None,
value: Optional[str] = "",
on_change: Optional[Handler[ValueChangeEventArguments]] = None,
) -> None:
"""Date+Time Input
This element extends Quasar's `QInput <https://quasar.dev/vue-components/input>`_ component with a date and time picker.
:param label: displayed label for the time input
:param with_seconds: include seconds in time picker
:param placeholder: text to show if no time is selected
:param value: the current time value
:param on_change: callback to execute when the value changes
"""
super().__init__(
tag="q-input", label=label, value=value, on_value_change=on_change
)
if placeholder is not None:
self._props["placeholder"] = placeholder
mask = "YYYY-MM-DD HH:mm"
time_picker_props = "format24h"
if with_seconds:
mask += ":ss"
time_picker_props += " with-seconds"
with self.add_slot("prepend"):
with (
icon("event")
.on("click", lambda: self.date_menu.open())
.classes("cursor-pointer")
):
with menu() as self.date_menu:
date(mask=mask).bind_value(self)
with self.add_slot("append"):
with (
icon("access_time")
.on("click", lambda: self.time_menu.open())
.classes("cursor-pointer")
):
with menu() as self.time_menu:
time(mask=mask).props(time_picker_props).bind_value(self)
date_input = DateInput(label="Date", placeholder="Enter date")
ui.label().bind_text_from(date_input, "value")
time_input = TimeInput(label="Time", placeholder="Enter time")
ui.label().bind_text_from(time_input, "value")
time_with_seconds_input = TimeInput(
label="Time", placeholder="Enter time (with seconds)", with_seconds=True
)
ui.label().bind_text_from(time_with_seconds_input, "value")
datetime_input = DateTimeInput(label="DateTime", placeholder="Enter datetime")
ui.label().bind_text_from(datetime_input, "value")
datetimesec_input = DateTimeInput(
label="DateTimeSec", placeholder="Enter datetime (with seconds)", with_seconds=True
)
ui.label().bind_text_from(datetimesec_input, "value")
ui.run() |
Motivation
Addresses NiceGUI Wishlist, about how NiceGUI does not have native
ui.date_input
andui.time_input
, and need to do https://nicegui.io/documentation/date#input_element_with_date_picker and https://nicegui.io/documentation/time#input_element_with_time_pickerImplementation
ui.menu
andui.button
for the button which opens the picker (reference: FR: Add an option to QBtnDropdown to hide the dropdown icon on the side quasarframework/quasar#10920 (comment))ui.color_input
as much as possible.range_input=True
Progress
I need some help for the pytest...
Review with care, particularly to the situation of
ui.date_input
withrange=True