Skip to content

Commit

Permalink
Add option to clear value of DatetimePicker (#3990)
Browse files Browse the repository at this point in the history
  • Loading branch information
hoxbro authored Oct 14, 2022
1 parent a7f880f commit c1afabc
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 6 deletions.
2 changes: 1 addition & 1 deletion panel/models/datetime_picker.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class DatetimePicker(InputWidget):
'''

value = String(help="""
value = Nullable(String, help="""
The initial or picked date.
""")

Expand Down
13 changes: 9 additions & 4 deletions panel/models/datetime_picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class DatetimePickerView extends InputWidgetView {

const {value, min_date, max_date, disabled_dates, enabled_dates, position, inline,
enable_time, enable_seconds, military_time, date_format, mode} = this.model.properties
this.connect(value.change, () => this._picker?.setDate(this.model.value))
this.connect(value.change, () => this.model.value ? this._picker?.setDate(this.model.value) : this._clear())
this.connect(min_date.change, () => this._picker?.set("minDate", this.model.min_date))
this.connect(max_date.change, () => this._picker?.set("maxDate", this.model.max_date))
this.connect(disabled_dates.change, () => this._picker?.set("disable", this.model.disabled_dates))
Expand Down Expand Up @@ -68,7 +68,7 @@ export class DatetimePickerView extends InputWidgetView {
this.input_el = input({type: "text", class: inputs.input, disabled: this.model.disabled})
this.group_el.appendChild(this.input_el)
this._picker = flatpickr(this.input_el, {
defaultDate: this.model.value,
defaultDate: this.model.value!,
minDate: this.model.min_date ? new Date(this.model.min_date) : undefined,
maxDate: this.model.max_date ? new Date(this.model.max_date) : undefined,
inline: this.model.inline,
Expand All @@ -86,6 +86,11 @@ export class DatetimePickerView extends InputWidgetView {
this._picker.minDateHasTime = true
}

protected _clear() {
this._picker?.clear()
this.model.value = null
}

protected _on_close(_selected_dates: Date[], date_string: string, _instance: flatpickr.Instance): void {
if (this.model.mode == "range" && !date_string.includes("to"))
return
Expand All @@ -98,7 +103,7 @@ export namespace DatetimePicker {
export type Attrs = p.AttrsOf<Props>

export type Props = InputWidget.Props & {
value: p.Property<string>
value: p.Property<string | null>
min_date: p.Property<string | null>
max_date: p.Property<string | null>
disabled_dates: p.Property<DatesList>
Expand Down Expand Up @@ -132,7 +137,7 @@ export class DatetimePicker extends InputWidget {
const DateStr = String
const DatesList = Array(Or(DateStr, Tuple(DateStr, DateStr)))
return {
value: [ String ],
value: [ Nullable(String), null ],
min_date: [ Nullable(String), null ],
max_date: [ Nullable(String), null ],
disabled_dates: [ DatesList, [] ],
Expand Down
56 changes: 55 additions & 1 deletion panel/tests/ui/widgets/test_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import pytest

from panel.io.server import serve
from panel.widgets import DatetimePicker
from panel.tests.util import wait_until
from panel.widgets import DatetimePicker, DatetimeRangePicker

try:
from playwright.sync_api import expect
Expand Down Expand Up @@ -566,3 +567,56 @@ def test_datetimepicker_name(page, port):

datetime_picker_with_name = page.locator('.datetimepicker-with-name')
expect(datetime_picker_with_name).to_have_text(name)


def test_datetimepicker_no_value(page, port, datetime_start_end):
datetime_picker_widget = DatetimePicker()

serve(datetime_picker_widget, port=port, threaded=True, show=False)
time.sleep(0.2)
page.goto(f"http://localhost:{port}")

datetime_picker = page.locator('.flatpickr-input')
assert datetime_picker.input_value() == ""

datetime_picker_widget.value = datetime_start_end[0]
wait_until(lambda: datetime_picker.input_value() == '2021-03-02 00:00:00', page)

datetime_picker_widget.value = None
wait_until(lambda: datetime_picker.input_value() == '', page)


def test_datetimerangepicker_no_value(page, port, datetime_start_end):
datetime_picker_widget = DatetimeRangePicker()

serve(datetime_picker_widget, port=port, threaded=True, show=False)
time.sleep(0.2)
page.goto(f"http://localhost:{port}")

datetime_picker = page.locator('.flatpickr-input')
assert datetime_picker.input_value() == ""

datetime_picker_widget.value = datetime_start_end[:2]
expected = '2021-03-02 00:00:00 to 2021-03-03 00:00:00'
wait_until(lambda: datetime_picker.input_value() == expected, page)

datetime_picker_widget.value = None
wait_until(lambda: datetime_picker.input_value() == '', page)


def test_datetimepicker_remove_value(page, port, datetime_start_end):
datetime_picker_widget = DatetimePicker(value=datetime_start_end[0])

serve(datetime_picker_widget, port=port, threaded=True, show=False)
time.sleep(0.2)
page.goto(f"http://localhost:{port}")

datetime_picker = page.locator('.flatpickr-input')
assert datetime_picker.input_value() == "2021-03-02 00:00:00"

# Remove values from the browser
datetime_picker.dblclick()
datetime_picker.press("Backspace")
datetime_picker.press("Escape")

wait_until(lambda: datetime_picker_widget.value is None, page)

0 comments on commit c1afabc

Please sign in to comment.