Skip to content

fix: dateInput() datesdisabled ignored non-default format (#4281) - #4434

Merged
cpsievert merged 2 commits into
rstudio:mainfrom
taekop:fix-4281-datesdisabled-format
Oct 2, 2026
Merged

cpsievert merged 2 commits into
rstudio:mainfrom
taekop:fix-4281-datesdisabled-format

Conversation

@taekop

@taekop taekop commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #4281, #3251.

dateInput()'s datesdisabled silently did nothing whenever format wasn't
the default yyyy-mm-dd. min/max avoid this problem by sending yyyy-mm-dd
strings through a plain data-min-date/data-max-date attribute, which the
client-side binding converts to real Date objects before handing them to
bootstrap-datepicker. datesdisabled, on the other hand, was rendered as
data-date-dates-disabled, a data-date-* attribute that bootstrap-datepicker
picks up and parses itself using the (possibly non-default) display format —
so a yyyy-mm-dd date string like 2012-03-01 would never match once format
was, say, dd/mm/yyyy.

This renames the attribute to a plain data-dates-disabled and has the
client-side date binding convert each entry the same way min/max already
are (via _newDate), before calling bootstrap-datepicker's setDatesDisabled
with real Date objects. daysofweekdisabled is untouched since it's just
integers and has no format dependency. updateDateInput() doesn't currently
support updating datesdisabled at all, so there's no corresponding
receiveMessage path to fix.

The disabled dates are applied before the initial value is set in
initialize(), because bootstrap-datepicker's setDatesDisabled() re-parses
the input text with the display format (which misreads 2-digit years). The
attribute is omitted when datesdisabled is NULL, like min/max.

Tests: tests/testthat/test-input-date.R checks the rendered attribute, and
tests/testthat/test-zzz-st2-input-date.R (shinytest2) checks the server value
and the disabled days for dd/mm/yyyy and mm/dd/yy, with and without
datesdisabled.

@CLAassistant

CLAassistant commented Sep 29, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

cpsievert

This comment was marked as resolved.

bootstrap-datepicker's setDatesDisabled() re-parses the input text with the
display format, turning 2-digit years like 12 into year 12 AD. Apply it before
setValue(), and omit the attribute when datesdisabled is NULL.
@taekop

taekop commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks for catching this, and for the precise repro and cause.

Pushed a follow-up commit:

  • _setDatesDisabled() now runs before setValue() in initialize(), as you suggested.
  • The data-dates-disabled attribute is now omitted when datesdisabled is NULL (same as min/max), so inputs that don't use it never go through setDatesDisabled().
  • Added a shinytest2 test (tests/testthat/test-zzz-st2-input-date.R) covering dd/mm/yyyy + datesdisabled, and mm/dd/yy with and without it. It checks the server value and that March 1-2 are disabled in the picker.
  • Minor items: Fixes #4281, #3251 (dateInput datesdisabled argument not working with different formats #3251 is the same bug), single-line NEWS bullet, shorter comment in R/input-date.R, overload moved above the generic ones. shiny.js is rebuilt.

Verification: with your repro app (plus one input with min/max) in Chrome via chromote, in America/Chicago and Asia/Tokyo, the previous commit gives 0012-02-29 for both mm/dd/yy inputs and no disabled days for mm/dd/yy + datesdisabled. With this commit all four inputs report 2012-02-29, and March 1-2 are disabled for the datesdisabled inputs only.

The new shinytest2 test passes on this commit (6/6) and fails 3 expectations on the previous one (both mm/dd/yy inputs report 0012-02-29, and no days are disabled for mm/dd/yy + datesdisabled). Like the other shinytest2 tests it is skipped on CRAN, Linux and Windows.

@taekop
taekop requested a review from cpsievert October 1, 2026 07:43

@cpsievert cpsievert left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @taekop! Would you be willing to make the same change to input_date() in https://github.com/posit-dev/py-shiny ?

Also, now that I think of it, do we need similar changes for dateRangeInput()?

@taekop

taekop commented Oct 2, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review! I checked dateRangeInput() and it doesn't need this: it has no datesdisabled argument, and its binding never calls setDatesDisabled, so there's nothing to parse with the wrong format. I also ran it in a real app with a mm/dd/yy format plus min/max and the values come back intact.

For py-shiny, input_date() has the same bug, and since it vendors shiny's JS the fix needs the Python attribute rename plus a JS re-sync together. I have that prepared locally with a Playwright test and will open the PR once this one is merged so the sync can come from main.

This comment was marked as resolved.

@cpsievert

Copy link
Copy Markdown
Collaborator

I have that prepared locally with a Playwright test and will open the PR once this one is merged so the sync can come from main.

That would be awesome, thanks!

@cpsievert
cpsievert merged commit bbc4384 into rstudio:main Oct 2, 2026
11 of 12 checks passed
taekop added a commit to taekop/py-shiny that referenced this pull request Oct 5, 2026
Emit data-dates-disabled instead of data-date-dates-disabled so the dates are parsed as yyyy-mm-dd by the client binding rather than by bootstrap-datepicker with the display format. Omit the attribute when datesdisabled is None. Update InputDate.expect_datesdisabled() to match. Needs the shiny.js from rstudio/shiny#4434.
@taekop

taekop commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

The py-shiny port is up in posit-dev/py-shiny#2523.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

datesdisabled in dateInput does not work for non-yyyy-mm-dd formats

4 participants