abradley2 / elm-datepicker / DatePicker

This module provides a styled date picker for Elm. You can check out the demo here.

To alter the color theme edit ./styl/Variables.styl, then run npm install && npm run build-styles.

This library depends heavily on justinmimbs/date as this provides a nice RD based wrapper around Dates that is agnostic to time/timezone, which is better suited for calendars. See the documentation there for any specific handling of the Date type.

Tea / Initialization


type Msg
    = NoOp
    | DateSelected Date Date
    | GetToday Date
    | PreviousMonth Date
    | NextMonth Date
    | SubmitClicked Date
    | CancelClicked
    | SetSelectionMode SelectionMode

You will first need to add the DatePicker.Msg to the type consumed by your update function so it recognizes this type.

import DatePicker
...
type Msg
    = FireZeMissiles
    | DatePickerMsg DatePicker.Msg

init : String -> ( Model, Platform.Cmd.Cmd Msg )

DatePicker.init returns an initialized record of DatePicker.Model. Do not throw out the returned command! The command is used to get today's current date which the date picker uses as the default for display. The string passed as the first argument must be a unique id for the date picker.

import DatePicker

init : ( Model, Cmd Msg )
init =
    let
        ( datePickerData, datePickerInitCmd ) =
            DatePicker.init "my-datepicker-id"
    in
    ( { datePickerData = datePickerData
      , selectedDate = Nothing
      }
    , Cmd.map DatePickerMsg datePickerInitCmd
    )

initFromDate : String -> Date -> Model

Initialize a date picker given a date to start from.

update : Msg -> Model -> ( Model, Platform.Cmd.Cmd Msg )

Use DatePicker.update to create updated date picker models from any message events. For a nice full working example check out the demo source here

import DatePicker exposing (Msg(..))
...
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        NoOp ->
            ( model, Cmd.none )

    DatePickerMsg datePickerMsg ->
        let
            (updatedPicker, pickerCmd) =
                DatePicker.update
                    datepickerMsg
                    model.datePickerData
        in
            ({ model
             | datePickerData = updatedPicker
             , selectedDate = datePickerData.selectedDate
            }
            , Cmd.map DatePickerMsg pickerCmd
            )


type alias Model =
{ id : String
, today : Maybe Date
, indexDate : Maybe Date
, currentMonthMap : Maybe (List ( Basics.Int
, Date ))
, previousMonthMap : Maybe (List ( Basics.Int
, Date ))
, selectedDate : Maybe Date
, previousSelectedDate : Maybe Date
, monthChange : MonthChange
, selectionMode : SelectionMode
, yearList : Maybe (List Basics.Int) 
}

The DatePicker.Model type needs to be added to any data structure that requires a picker instance

import DatePicker
...
type alias Model =
    { datePickerData : DatePicker.Model
    }
}

This is mostly an opaque type you don't have to worry about, though there are some important fields you will want to use:

Rendering and Settings

view : Model -> Props -> Html Msg

The main view for the date picker. Use Html.map so the returned type doesn't conflict with your view's type.

import DatePicker
...
view : Model -> Html Msg
view model =
    Html.map DatePickerMsg <|
        DatePicker.view
            model.datePickerData
            DatePicker.defaultProps


type alias Props =
{ canSelectYear : Basics.Int -> Basics.Bool
, canSelectMonth : Basics.Int -> Time.Month -> Basics.Bool
, canSelectDate : Date -> Basics.Bool
, hideFooter : Basics.Bool
, monthDisplay : Time.Month -> String
, daySymbol : Time.Weekday -> String
, selectedDateDisplay : Maybe Date -> Date -> String
, okButtonText : String
, cancelButtonText : String 
}

The second argument passed to DatePicker.view. These are configuration properties that generally determine the range of selectable dates. Extend off DatePicker.defaultProps to avoid having to define all of these when you only wish to configure a few.


Property Descriptions

given the year, return whether this year is allowed to be selected

canSelectYear : Int -> Bool

given the year and the month, return whether this month is allowed to be selected

canSelectMonth : Int -> Month -> Bool

given the date, return whether this is allowed to be selected

canSelectDate : Date -> Bool

should the footer of the calendar with the "CANCEL" and "OK" buttons display

hideFooter : Bool

text for the "OK" button which is enabled whenever a date is selected. defaults to "OK"

okButtonText : String

text for the "CANCEL" button. Defaults to "CANCEL"

cancelButtonText : String

return whatever text to show given the month (this is just below the calendar header)

monthDisplay : Time.Month -> String

return whatever text (generally a single letter or two) to show given the weekday (these are the small letters the top of the month)

daySymbol : Time.Weekday -> String

return whatever text to show given the selected Date (This is the large display text on the calendar header) The first date is the "selectedDate" which may not yet be defined. The second is the "indexDate" which is the current placeholder date being used (generally set to today's date by default)

selectedDateDisplay : Maybe Date -> Date -> String

defaultProps : Props

Use the default props if you don't want to support any sort of configuration. These mostly center around limiting the user to a specific selection range of dates. By default, nothing is restricted.

Here's an example of how you might configure these:

getDatePickerProps : DatePicker.Props
getDatePickerProps =
    let
        defaultProps =
            DatePicker.defaultProps
    in
    { defaultProps
        | canSelectYear = \year -> year < 2020
        , okButtonText = "CONFIRM"
    }

Helpers

setIndexDate : Model -> Date -> Model

Takes any of type DatePicker.Model and returns a new one with the given index date. It is important to not just set indexDate directly as this will not refresh the data to completely reflect this

Types


type SelectionMode

Represents the current mode the picker is set to

type SelectionMode
    = Calendar
    | YearPicker