Skip to content

Instantly share code, notes, and snippets.

@pdamoc
Created February 16, 2016 17:15
Show Gist options
  • Save pdamoc/228421e523d1f7a8a86b to your computer and use it in GitHub Desktop.
Save pdamoc/228421e523d1f7a8a86b to your computer and use it in GitHub Desktop.
TableSort
{
"version": "1.0.0",
"summary": "helpful summary of your project, less than 80 characters",
"repository": "https://github.com/user/project.git",
"license": "BSD3",
"source-directories": [
"."
],
"exposed-modules": [],
"dependencies": {
"elm-lang/core": "3.0.0 <= v < 4.0.0",
"evancz/elm-effects": "2.0.1 <= v < 3.0.0",
"evancz/elm-html": "4.0.2 <= v < 5.0.0",
"evancz/elm-http": "3.0.0 <= v < 4.0.0",
"evancz/start-app": "2.0.2 <= v < 3.0.0"
},
"elm-version": "0.16.0 <= v < 0.17.0"
}
import Html exposing (..)
import Html.Events exposing (onClick)
import StartApp.Simple exposing (start)
-- Generic
type alias HeadItem a =
{ sorter: (a -> a -> Basics.Order)
, toHtml : (a -> Html)
}
type alias Table a =
{ data: List a
, head : List (String, HeadItem a)
}
cmp : (a -> comparable) -> a -> a -> Order
cmp f a b =
compare (f a) (f b)
toText : (a -> String) -> a -> Html
toText f record = text <| (f record)
type alias Model a=
{ table : Table a
, currentSort : String
, ascending : Bool
}
type Action = Sort String
update : Action -> Model a -> Model a
update action model =
case action of
Sort str ->
let
headItem =
List.filter (\(s,_) -> s == str) model.table.head
|> List.map snd |> List.head
ascending =
if str == model.currentSort then not model.ascending else model.ascending
data' =
case headItem of
Nothing -> model.table.data
Just hi ->
if ascending
then List.sortWith hi.sorter model.table.data
else List.reverse <| List.sortWith hi.sorter model.table.data
in
Model (Table data' model.table.head) str ascending
(=>) : a -> b -> ( a, b )
(=>) = (,)
tableHead : Signal.Address Action -> ( String, a ) -> Html
tableHead address (name, headItem) =
th []
[button [onClick address (Sort name)] [text name]]
rowView : List (String, HeadItem a) -> a -> Html
rowView head row =
let
viewCell hi = td [] [hi.toHtml row]
in
tr [] (List.map viewCell (List.map snd head))
view : Signal.Address Action -> Model a -> Html
view address model =
table []
([ tr []
(List.map (tableHead address) model.table.head)
] ++ (List.map (rowView model.table.head) model.table.data))
--- Specific
type alias Person =
{ name : String
, email : String
, age : Int
}
headers : List (String, HeadItem Person)
headers =
[ "Name" => HeadItem (cmp .name) (toText .name)
, "Email" => HeadItem (cmp .email) (toText .email)
, "Age" => HeadItem (cmp .age) (toText (toString << .age) )
]
samplePersons : List Person
samplePersons =
[ Person "John Doe" "[email protected]" 30
, Person "John Wayne" "[email protected]" 60
, Person "John Bond" "[email protected]" 40
]
init : Model Person
init = Model (Table samplePersons headers) "Name" True
main : Signal Html
main = start {model=init, update=update, view=view}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment