Repository: holoviz/panel

Issue:
Clearing value of a DatetimePicker
#### Description of expected behavior and the observed behavior
Not sure if this is a bug or a new feature to Panel. Let's say I have a layout consisting of a button named "Edit", a DatetimePicker disabled with no default value, and a button named "Submit". At the time of initialization, the value of DatetimePicker is Null. The way these objects interact is as follows:
- Click "Edit" button, DatetimePicker is enabled so user can select a specific time value.
- Click "Submit" button, the selected time value will be pushed to the DB, and the DatetimePicker will be disabled and reset back to Null.

I have tried several ways with no success in clearing the value of the DatetimePicker.

#### Complete, minimal, self-contained example code that reproduces the issue

```
time_widget = pn.widgets.DatetimePicker(disabled=True)
time_widget.value = now()

# how to set value back to None?
time_widget.value = None/pandas.NaT/np.nan => all causes error
```



Discussion:

Resolving patch:
diff --git a/panel/models/datetime_picker.py b/panel/models/datetime_picker.py
--- a/panel/models/datetime_picker.py
+++ b/panel/models/datetime_picker.py
@@ -10,7 +10,7 @@ class DatetimePicker(InputWidget):
 
     '''
 
-    value = String(help="""
+    value = Nullable(String, help="""
     The initial or picked date.
     """)
 


Test patch:
diff --git a/panel/tests/ui/widgets/test_input.py b/panel/tests/ui/widgets/test_input.py
--- a/panel/tests/ui/widgets/test_input.py
+++ b/panel/tests/ui/widgets/test_input.py
@@ -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
@@ -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)