Created
November 13, 2016 06:21
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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