holoviz / panel

Panel: The powerful data exploration & web app framework for Python
https://panel.holoviz.org
BSD 3-Clause "New" or "Revised" License
4.61k stars 500 forks source link

Add MonthPicker and other month picker widgets. #4820

Open everton3x opened 1 year ago

everton3x commented 1 year ago

Is your feature request related to a problem? Please describe.

Although there are several widgets related to date/datetime, I missed one for selecting months/years, something like <input type="month">.

Describe the solution you'd like

The solution would be to include a widget similar to DatePicker (which generates an <input type="date"> but with the html attribute type="month".

It would be very interesting to also have a MonthRangeSlider, MonthSlider, MonthInput.

Describe alternatives you've considered

I tried to implement one based on the Material UI example, but using Bootstrap:

class BootstrapBase(ReactiveHTML):
    __javascript__ = ['https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js']
    __css__ = ['https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css']

pn.extension()

class BootstrapMonthPicker(BootstrapBase):
    value = param.String(default='')

    _template = """
    <div id="month-field" class="mb-3">
        <label class="form-label">Período</label>
        <input id="month-input" type="month" class="form-control" value="${value}"></input>
    </div>
    """

    _dom_events = {'month-input': ['change']}

... but that didn't work (an error is thrown: ValueError: The depends decorator only accepts string types referencing a parameter or parameter instances, found BootstrapMonthPicker type instead.)

Additional context

Nothing more to add.

hoxbro commented 1 year ago

Running your code works on the latest dev release. The release is expected this week.

image

Note that the type="month" is not supported on Firefox.

everton3x commented 1 year ago

I finally got it to work this way:

import panel as pn
from panel.reactive import ReactiveHTML
import param
from datetime import datetime

class MonthPicker(ReactiveHTML):
    value = param.String(default='')
    name = param.String(default='')
    _child_config = {
        'name': 'literal'
    }
    _template = """
    <div class="mb-3" id="month-picker">
      <label id="month-label" for="month-input" class="form-label">${name}</label>
      <input id="month-input" type="month" class="form-control" value="${value}"></input>
    </div>
    """
    _dom_events = {'month-input': ['change']}
    _extension_name = 'month-picker'
    __javascript__ = ['https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js']
    __css__ = ['https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css']

pn.extension(
    'month-picker'
)

ano = datetime.now().year
mes = str(datetime.now().month).zfill(2)
periodo = f'{ano}-{mes}'
month_picker = MonthPicker(name='Período', value=periodo)

app = pn.Row(month_picker)
app.servable()

image