Skip to content

Instantly share code, notes, and snippets.

@ryan-haskell
Created November 13, 2016 06:21
Show Gist options
  • Save ryan-haskell/8d248b5dbd761c640ff213b94f52f24f to your computer and use it in GitHub Desktop.
Save ryan-haskell/8d248b5dbd761c640ff213b94f52f24f to your computer and use it in GitHub Desktop.
Simple sortable table functionality implemented with Try Elm | http://elm-lang.org/try
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Html.App as App
type CellType
= String
| Int
| Bool
type alias Column = String
type alias Cell =
{ column: Column
, value: String
}
type alias Row =
{ selected: Bool
, cells: List Cell
}
type alias Model =
{ headers: List Column
, rows: List Row
, sortBy: Maybe Column
, sortAscending: Bool
}
initialModel : Model
initialModel =
Model
[ "Name"
, "Age"
, "Description"
]
[ Row False
[ (Cell "Name" "Ryan")
, (Cell "Age" "22")
, (Cell "Description" "Stupid")
]
, Row False
[ (Cell "Name" "Steve")
, (Cell "Age" "25")
, (Cell "Description" "Not a real person")
]
]
Nothing
True
main =
App.beginnerProgram
{ model = initialModel
, view = view
, update = update
}
type Msg
= ToggleRowSelection Row
| ClearSelections
| SortByColumn Column
update : Msg -> Model -> Model
update msg model =
case msg of
SortByColumn column ->
if model.sortBy == Just column then
{ model | sortAscending = (not model.sortAscending) }
else
{ model
| sortBy = Just column
, sortAscending = True
}
ToggleRowSelection clickedRow ->
{ model | rows =
(List.map (\row ->
if clickedRow == row then
{row | selected = (not row.selected)}
else row
) model.rows)
}
_ ->
model
view : Model -> Html Msg
view model =
div
[ style
[ ("width", "100%")
, ("height", "100%")
, ("backgroundColor", "#333")
, ("color", "white")
]
]
[ table
[ style
[ ("width", "100%")
, ("padding", "10px")
]
]
([ thead
[ style
[ ("backgroundColor", "#ccc")
, ("color", "black")
, ("cursor", "pointer")
--, ("fontWeight", "bold")
, ("textTransform", "uppercase")
]
]
(renderHeaders model)
] ++ renderRows model)
]
renderHeaders : Model -> List (Html Msg)
renderHeaders model =
List.map (renderHeader model) model.headers
renderHeader : Model -> Column -> Html Msg
renderHeader model column =
let
sortColumn =
Maybe.withDefault "" model.sortBy
icon : String
icon =
if sortColumn == column then
if model.sortAscending then
"▲"
else
"▼"
else
""
in
td
[ style [("padding", "10px")]
, onClick (SortByColumn column)
]
[ text column
, span [ style [("float", "right")]] [text icon]
]
renderRows : Model -> List (Html Msg)
renderRows model =
let
rows : List Row
rows = List.sortWith (sortRows model) model.rows
in
(List.map renderRow rows)
sortRows : Model -> Row -> Row -> Order
sortRows model a b =
let
sortColumn =
Maybe.withDefault "" model.sortBy
filteredA =
List.filter (\cell -> cell.column == sortColumn) a.cells
aCell =
Maybe.withDefault (Cell sortColumn "") (List.head filteredA)
filteredB =
List.filter (\cell -> cell.column == sortColumn) b.cells
bCell =
Maybe.withDefault (Cell sortColumn "") (List.head filteredB)
in
if aCell.value < bCell.value then
if model.sortAscending then LT else GT
else
if model.sortAscending then GT else LT
renderRow : Row -> Html Msg
renderRow row =
tr
[ style
[ ("backgroundColor", if row.selected then "#ccf" else "#fff")
, ("color", "black")
]
, onClick (ToggleRowSelection row)
]
( List.map renderCell row.cells )
renderCell : Cell -> Html Msg
renderCell cell =
td
[ style [("padding", "10px")] ]
[ text cell.value ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment