Skip to content

Instantly share code, notes, and snippets.

@kyasu1
Last active February 14, 2017 05:02
Show Gist options
  • Select an option

  • Save kyasu1/edecc747f5339db69abcbab4d37102c8 to your computer and use it in GitHub Desktop.

Select an option

Save kyasu1/edecc747f5339db69abcbab4d37102c8 to your computer and use it in GitHub Desktop.
A date input with separated fields for using with elm-form
module DateInput exposing (view, validate)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput, onFocus, onBlur)
import Regex
import Form exposing (InputType(..))
import Form.Field exposing (FieldValue(..))
import Form.Validate
import Form.Error as Error
import Date exposing (Date)
import Date.Extra as Date
view : Form.FieldState e String -> Html Form.Msg
view state =
div []
[ span []
[ input
[ type_ "text"
, onInput (yearToDateJa state)
, onFocus (Form.Focus state.path)
, onBlur (Form.Blur state.path)
, value (state.value |> Maybe.map stringToYear |> Maybe.withDefault "")
]
[]
--, span [ class [ MyCss.Label ] ] [ text "年" ]
, input
[ type_ "text"
, onInput (monthToDate state)
, onFocus (Form.Focus state.path)
, onBlur (Form.Blur state.path)
, value (state.value |> Maybe.map stringToMonth |> Maybe.withDefault "")
]
[]
-- , span [ class [ MyCss.Label ] ] [ text "月" ]
, input
[ type_ "text"
, onInput (dayToDate state)
, onFocus (Form.Focus state.path)
, onBlur (Form.Blur state.path)
, value (state.value |> Maybe.map stringToDay |> Maybe.withDefault "")
]
[]
-- , span [ class [ MyCss.Label ] ] [ text "日" ]
]
]
stringToYear : String -> String
stringToYear isoDate =
case String.split "-" isoDate of
[ y, _, _ ] ->
y
_ ->
""
filterYear : String -> String
filterYear year =
let
year_ =
"0000" ++ year |> String.right 4
in
if validateYear year_ then
year_ |> String.toUpper
else
String.dropRight 1 year
validateYear : String -> Bool
validateYear year =
Regex.contains (Regex.regex "^[0-9]{0,4}$") year
yearToDateJa : Form.FieldState e String -> String -> Form.Msg
yearToDateJa state year =
let
year_ =
filterYear year
in
case state.value of
Just date ->
let
newDate =
case String.split "-" date of
[ y, m, d ] ->
concatDate year_ m d
_ ->
concatDate year_ "" ""
in
Form.Input state.path Text (String newDate)
Nothing ->
Form.Input state.path Text (String (concatDate year_ "" ""))
stringToMonth : String -> String
stringToMonth date =
case String.split "-" date of
[ _, m, _ ] ->
m
_ ->
""
filterMonth : String -> String
filterMonth month =
let
month_ =
"00" ++ month |> String.right 2
in
if validateMonth month_ then
month_
else
String.dropRight 1 month
validateMonth : String -> Bool
validateMonth month =
if Regex.contains (Regex.regex "^[0-9]{0,2}$") month then
case String.toInt month of
Ok value ->
if value >= 1 && value <= 12 then
True
else
False
Err _ ->
False
else
False
monthToDate : Form.FieldState e String -> String -> Form.Msg
monthToDate state month =
let
month_ =
filterMonth month
in
case state.value of
Just date ->
let
newDate =
case String.split "-" date of
[ y, m, d ] ->
concatDate y month_ d
_ ->
concatDate "" month_ ""
in
Form.Input state.path Text (String newDate)
Nothing ->
Form.Input state.path Text (String (concatDate "" month_ ""))
stringToDay : String -> String
stringToDay date =
case String.split "-" date of
[ _, _, d ] ->
d
_ ->
""
dayToDate : Form.FieldState e String -> String -> Form.Msg
dayToDate state day =
let
day_ =
filterDay day
in
case state.value of
Just date ->
let
newDate =
case String.split "-" date of
[ y, m, d ] ->
concatDate y m day_
_ ->
concatDate "" "" day_
in
Form.Input state.path Text (String newDate)
Nothing ->
Form.Input state.path Text (String (concatDate "" "" day_))
filterDay : String -> String
filterDay day =
let
day_ =
"00" ++ day |> String.right 2
in
if validateDay day_ then
day_
else
String.dropRight 1 day
validateDay : String -> Bool
validateDay day =
if Regex.contains (Regex.regex "^[0-9]{0,2}$") day then
case String.toInt day of
Ok value ->
if value >= 1 && value <= 31 then
True
else
False
Err _ ->
False
else
False
validate : Form.Validate.Validation e Date
validate field =
case Form.Field.asString field of
Just date ->
case Date.fromIsoString date of
Just date_ ->
if (Date.day date_) == (date |> String.right 2 |> String.toInt |> Result.withDefault 0) then
Result.Ok date_
else
Result.Err (Error.value Error.InvalidDate)
Nothing ->
Result.Err (Error.value Error.InvalidDate)
Nothing ->
Result.Err (Error.value Error.InvalidDate)
concatDate : String -> String -> String -> String
concatDate y m d =
y ++ "-" ++ m ++ "-" ++ d
module Main exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Form exposing (Form)
import Form.Field as Field
import Form.Validate as Validate exposing (..)
import Form.Input as Input
import Date exposing (Date)
import DateInput
type alias Customer =
{ id : String
, date : Date
}
type alias Model =
{ form : Form () Customer }
type Msg
= NoOp
| FormMsg Form.Msg
init : ( Model, Cmd Msg )
init =
( { form = Form.initial [] validation }, Cmd.none )
validation : Validation () Customer
validation =
map2 Customer
(field "id" string)
(field "date" DateInput.validate)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg ({ form } as model) =
case msg of
NoOp ->
( model, Cmd.none )
FormMsg formMsg ->
{ model | form = Form.update validation formMsg form } ! []
view : Model -> Html Msg
view { form } =
Html.map FormMsg (formView form)
formView : Form () Customer -> Html Form.Msg
formView form =
let
date =
Form.getFieldAsString "date" form
in
div []
[ DateInput.view date
, Input.dumpErrors form
]
main =
Html.program
{ init = init
, update = update
, view = view
, subscriptions = \_ -> Sub.none
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment