amp-date-picker

Edit on Github
Open in Playground

Experimental Mode

This example uses the following experimental feature: [amp-date-picker]. Enable the experiment via the button below. Some components require the AMP Dev Channel to be enabled as well. Learn more here.

Enable Dev Channel

Introduction

amp-date-picker is an AMP component which allows to select a single date or a range of dates. Its implementation is based on react-dates

Setup

Include the amp-date-picker component.

<script async custom-element="amp-date-picker" src="https://cdn.ampproject.org/v0/amp-date-picker-0.1.js"></script>

Include the amp-bind component to set variables based on the selected date.

<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>

Include the amp-mustache component to display an info panel below the date picker.

<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.1.js"></script>

Include the amp-lightbox component to display a date picker inside a fullscreen lightbox view.

<script async custom-element="amp-lightbox" src="https://cdn.ampproject.org/v0/amp-lightbox-0.1.js"></script>

Include the amp-form component for creating forms.

<script async custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-form-0.1.js"></script>

In order to personalize amp-date-picker style, you can use classes such as CalendarMonth_caption which are inherited from react-dates. amp-date-picker also exposes CSS classes which you can use in CSS rule, like amp-date-picker-selecting, which is applied to the date input the user is editing.

<style amp-custom>
.CalendarMonth_caption {
  color: #fff;
}

[type="range"] .amp-date-picker-selecting {
  border-bottom-color: #b60845;
  color: #b60845;
}

.align-content-center,
.align-content-center .amp-date-picker-calendar-container {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  flex-direction: row;
}

amp-lightbox {
  background: rgba(0, 0, 0, .75);
}
</style>

Single Date Picker

amp-date-picker with type=single can be used for selecting a single date. You can use amp-mustache with info-template attribute to show an info-panel below the calendar, here we are showing the date that you just selected. info-template also enables AMP binding making available variables which have been set with AMP.setState. A placeholder is required for the component. For a single date, this can take the form: <input amp-date-placeholder placeholder="Pick a date">. amp-date-picker introduces the clear action that can be called after clicking on a button to clear the date selection; it requires the show-clear-date attribute.

Example

<amp-date-picker id="simple-date-picker"
  type="single"
  mode="overlay"
  layout="container"
  on="select:AMP.setState({date1: event.date, dateType1: event.id})"
  format="YYYY-MM-DD"
  open-after-select
  input-selector="[name=date1]"
  class="mr1 ml1 flex picker">
  <div class="ampstart-input inline-block mt1">
    <input class="border-none p0"
      name="date1"
      placeholder="Pick a date">
  </div>
  <button class="ampstart-btn m1 caps"
    on="tap: simple-date-picker.clear">Clear</button>
  <template type="amp-mustache"
    info-template>
    <span [text]="date1 != null ? 'You picked ' + date1 + '.' : 'You will see your chosen date here.'">You will see your chosen date here.</span>
  </template>
</amp-date-picker>

In addition, you can also use amp-mustache to create templates for custom date markup, such as an icon instead of the number of the month. Here we are using a taco icon in place of the number of the month with a frequency of 2 weeks every Tuesday. Common use cases could be dates of the month where the price of an item is fixed to a specific number.

Example

<amp-date-picker id="simple-date-picker-2"
  type="single"
  mode="overlay"
  layout="container"
  on="select:AMP.setState({date2: event.date, dateType2: event.id})"
  locale="en"
  format="YYYY-MM-DD"
  open-after-select
  input-selector="[name=date2]"
  class="mr1 ml1 flex picker">
  <div class="ampstart-input inline-block mt1">
    <input class="border-none p0"
      name="date2"
      placeholder="Pick a date">
  </div>
  <button class="ampstart-btn m1 caps"
    on="tap: simple-date-picker-2.clear">Clear</button>
  <template type="amp-mustache"
    date-template
    dates="FREQ=WEEKLY;DTSTART=20180101T000000Z;INTERVAL=2;WKST=SU;BYDAY=TU"
    id="tacos2">
    <span>🌮</span>
    <span class="taco-tuesday"></span>
  </template>
  <template type="amp-mustache"
    info-template>
    <span [text]="date2 ? 'You picked ' + date2 + '.' +
      (dateType2 == 'tacos2' ? ' Happy Taco Tuesday!' : '') : ''">You will see your chosen date here.</span>
  </template>
</amp-date-picker>

amp-date-picker supports a range of attributes, for example highlighted and blocked. Find the complete list in the official doc. The blocked attribute allows to specify a space separated list of ISO 8601 dates and RFC 5545 RRULEs specifying disallowed dates. The highlighted attributes a space separated list of ISO 8601 dates and RFC 5545 RRULEs specifying dates displayed with a highlight style. Here every Black Friday is highlighted, while every Christmas is blocked.

Example

<amp-date-picker id="simple-date-picker-3"
  type="single"
  mode="overlay"
  layout="container"
  on="select:AMP.setState({date3: event.date ? event.date : ''})"
  locale="en"
  format="YYYY-MM-DD"
  open-after-select
  highlighted="FREQ=YEARLY;DTSTART=20171124T110000Z;UNTIL=20171126T040000Z;BYMONTH=11;BYDAY=+4TH;WKST=SU"
  blocked="FREQ=YEARLY;WKST=SU;BYMONTH=12;BYMONTHDAY=25"
  input-selector="[name=date3]"
  class="mr1 ml1 flex picker">

  <div class="ampstart-input inline-block mt1">
    <input class="border-none p0"
      name="date3"
      placeholder="Pick a date">
  </div>
  <button class="ampstart-btn m1 caps"
    on="tap:simple-date-picker-3.clear">Clear</button>
  <template type="amp-mustache"
    info-template>
    <span [text]="date3 ? 'You picked ' + date3 + '.' : 'You will see your chosen date here.'">You will see your chosen date here.</span>
  </template>
</amp-date-picker>

Date Range Picker

amp-date-picker with type=range can be used for selecting a date range. By default, amp-date-picker disables past dates, use min attribute to enable them.

Example

  <button class="ampstart-btn m1 caps"
    on="tap:range-date-picker.setDates(startDate='2017-10-26',endDate='2017-11-04')">Set date range</button>
  <amp-date-picker type="range"
    mode="overlay"
    id="range-date-picker"
    on="
  select:
    AMP.setState({
        dates: event.dates,
        startDate: event.start,
        endDate: event.end
    })"
    format="YYYY-MM-DD"
    open-after-select
    min="2017-10-26"
    start-input-selector="#range-start"
    end-input-selector="#range-end"
    class="mr1 ml1 flex picker">
    <div class="ampstart-input inline-block mt1">
      <input class="border-none p0"
        id="range-start"
        placeholder="Start date">
    </div>
    <div class="ampstart-input inline-block mt1">
      <input class="border-none p0"
        id="range-end"
        placeholder="End date">
    </div>
    <button class="ampstart-btn m1 caps"
      on="tap:range-date-picker.clear">Clear</button>
    <template type="amp-mustache"
      info-template>
      <span [text]="(startDate && endDate ?
      'You picked ' + startDate.date + ' as start date and ' + endDate.date + ' as end date.' :
      'You will see your chosen dates here.')">
        You will see your chosen dates here.
      </span>
    </template>
  </amp-date-picker>

External Configuration

It's possible to configure the amp-date-picker preferences by using an external json. We use the following JSON at the URL /json/amp-date-picker.json:

  {
    "templates": [{
      "id": "spooky",
      "dates": [
        "FREQ=YEARLY;DTSTART=20180101T160000Z;WKST=SU;BYMONTH=10;BYMONTHDAY=31",
        "FREQ=MONTHLY;DTSTART=20180101T160000Z;WKST=SU;BYDAY=FR;BYMONTHDAY=13"
      ]
    }]
  }

For dates that match the list of dates in the JSON blob, the template with id="spooky" will be used to render that day in the calendar. In this case, these dates are Friday the 13ths, and Halloween.

Example

<amp-date-picker id="src-picker"
  type="single"
  mode="overlay"
  layout="container"
  format="YYYY-MM-DD"
  src="https://ampbyexample.com/json/amp-date-picker.json"
  input-selector="#src-input"
  class="m1 flex">
  <div class="ampstart-input inline-block mt1">
    <input class="border-none p0"
      id="src-input"
      placeholder="Pick a date">
  </div>
  <button class="ampstart-btn m1 caps"
    on="tap: src-picker.clear">Clear</button>
  <template type="amp-mustache"
    date-template
    id="spooky">
    <div class="align-content-center">
      <span>🙀</span>
      <span>{{D}}</span>
    </div>
  </template>
</amp-date-picker>

Static date picker

amp-date-picker with mode="static" can display a calendar view. The static picker can be used with or without an attached input.

Example

  <div class="flex align-content-center">
    <div class="ampstart-input inline-block mt1">
      <input class="border-none p0"
        id="static-picker-input"
        placeholder="Pick a date">
    </div>
    <button class="ampstart-btn m1 caps"
      on="tap:static-picker.clear">Clear</button>
  </div>
  <amp-date-picker id="static-picker"
    type="single"
    mode="static"
    layout="fixed-height"
    height="360"
    format="YYYY-MM-DD"
    input-selector="#static-picker-input"
    class="align-content-center">
  </amp-date-picker>

amp-date-picker can display inside a modal lightbox. The activate event opens the lightbox if the user focuses the picker's connected input elements and presses the down arrow key. deactivate is triggered when the user presses escape when interacting with the calendar view. For a touch-only interface box, the on="tap:..." attribute opens the picker when the user taps on the input.

Example

Choose your travel dates

  <p>Choose your travel dates</p>
  <div class="flex">
    <div class="ampstart-input inline-block mt1">
      <input class="border-none p0"
        id="lb-start"
        placeholder="Start date"
        on="tap:lb.open"
        role="textbox"
        tabindex="0">
    </div>
    <div class="ampstart-input inline-block mt1">
      <input class="border-none p0"
        id="lb-end"
        placeholder="End date"
        on="tap:lb.open"
        role="textbox"
        tabindex="0">
    </div>
    <button class="ampstart-btn m1 caps"
      on="tap:lb-picker.clear">Clear</button>
  </div>
  <amp-lightbox id="lb"
    layout="nodisplay">
    <button class="ampstart-btn absolute m1 caps"
      on="tap:lb.close"
      tabindex="0">Close</button>
    <div class="align-content-center">
      <amp-date-picker id="lb-picker"
        type="range"
        mode="static"
        layout="fixed-height"
        height="360"
        format="MM/DD/YYYY"
        on="activate: lb.open;
            deactivate: lb.close;"
        start-input-selector="#lb-start"
        end-input-selector="#lb-end"></amp-date-picker>
    </div>
  </amp-lightbox>

Fullscreen lightbox date picker

amp-date-picker can also display as a fullscreen view inside a lightbox. The fullscreen attribute tells the date picker to take up the space in its container and allow its content to scroll vertically.

Example

Choose your travel dates

  <p>Choose your travel dates</p>
  <div class="flex">
    <div class="ampstart-input inline-block mt1">
      <input class="border-none p0"
        id="lb-fullscreen-start"
        placeholder="Start date"
        on="tap:lb-fullscreen.open"
        role="textbox"
        tabindex="0">
    </div>
    <div class="ampstart-input inline-block mt1">
      <input class="border-none p0"
        id="lb-fullscreen-end"
        placeholder="End date"
        on="tap:lb-fullscreen.open"
        role="textbox"
        tabindex="0">
    </div>
    <button class="ampstart-btn m1 caps"
      on="tap:lb-fullscreen-picker.clear">Clear</button>
  </div>
  <amp-lightbox id="lb-fullscreen"
    layout="nodisplay">
    <button class="ampstart-btn m1 absolute caps z3"
      on="tap:lb-fullscreen.close"
      tabindex="0">Close</button>
    <amp-date-picker id="lb-fullscreen-picker"
      fullscreen
      layout="fill"
      mode="static"
      type="range"
      number-of-months="12"
      format="MM/DD/YYYY"
      on="activate: lb-fullscreen.open;
            deactivate: lb-fullscreen.close;"
      start-input-selector="#lb-fullscreen-start"
      end-input-selector="#lb-fullscreen-end"></amp-date-picker>
  </amp-lightbox>

Date picker in a form

amp-date-picker integrates with AMP forms. If you don't provide an input for a static picker, it will create a hidden input to submit in the form.

Example

<form method="post"
  class="p2"
  action-xhr="/components/amp-form/submit-form-xhr"
  target="_top">
  <amp-date-picker id="form-picker"
    type="single"
    mode="static"
    layout="fixed-height"
    height="360"
    format="YYYY-MM-DD">
  </amp-date-picker>
  <input type="submit"
    class="ampstart-btn caps">
  <div submit-success>
    <template type="amp-mustache">
      Success! Thanks for trying the
      <code>amp-form</code> demo!
    </template>
  </div>
  <div submit-error>
    <template type="amp-mustache">
      Error!
    </template>
  </div>
</form>