Skip to content

Instantly share code, notes, and snippets.

@fpapado
Created December 27, 2017 11:34
Show Gist options
  • Save fpapado/4b2a1d47ffcca63e66d5f0ee8f1bb82f to your computer and use it in GitHub Desktop.
Save fpapado/4b2a1d47ffcca63e66d5f0ee8f1bb82f to your computer and use it in GitHub Desktop.
Elm nested updates
module Main exposing (..)
-- Using let..in, newWhatever and inline functions
import Dict exposing (Dict)
type alias Model =
{ something : String
, somethingElse : String
, items : Dict String Item
}
type alias Item =
{ name : String
, value : Int
, selected : Bool
}
initModel : Model
initModel =
{ something = "Hello"
, somethingElse = "World"
, items =
Dict.fromList
[ ( "APPLE", Item "apple" 1 False )
, ( "ORANGE", Item "orange" 2 False )
]
}
type Msg
= SelectItem String
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
SelectItem itemStringId ->
let
-- inline function to select item and deselect others
setSelected ( id, item ) =
if id == itemStringId then
( id, { item | selected = True } )
else
( id, { item | selected = False } )
-- this is silly, but we'll take care of it later
-- newSomething is very common for these updates
newItems =
model.items
|> Dict.toList
|> List.map setSelected
|> Dict.fromList
in
{ model | items = newItems } ! []
module Main exposing (..)
-- Here, we have a dedicated function to keep update clean
import Dict exposing (Dict)
type alias Model =
{ something : String
, somethingElse : String
, items : Dict String Item
}
type alias Item =
{ name : String
, value : Int
, selected : Bool
}
initModel : Model
initModel =
{ something = "Hello"
, somethingElse = "World"
, items =
Dict.fromList
[ ( "APPLE", Item "apple" 1 False )
, ( "ORANGE", Item "orange" 2 False )
]
}
type Msg
= SelectItem String
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
SelectItem itemStringId ->
let
newItems =
updateSelectedItem itemStringId model.items
in
{- Could even be:
{model | items = setSelectedItem itemStringId model.items}
and then we'd skip the let..in
-}
{ model | items = newItems } ! []
updateSelectedItem : comparable -> Dict comparable Item -> Dict comparable Item
updateSelectedItem itemId itemsDict =
let
setSelected ( id, item ) =
if id == itemId then
( id, { item | selected = True } )
else
( id, { item | selected = False } )
in
itemsDict
|> Dict.toList
|> List.map setSelected
|> Dict.fromList
-- You can even think of more updateSpecificModelPart functions for more nesting
module Main exposing (..)
{- Here, we change the definition of model to have selected as top level
Nested updates in general might mean some restructuring is due. Once an update
grows too large, you'd want sub-update functions anyway, so this is already a
step in that direction.
-}
import Dict exposing (Dict)
type alias Model =
{ something : String
, somethingElse : String
, items : Dict String Item
, selectedItem : Maybe String
}
type alias Item =
{ name : String
, value : Int
}
initModel : Model
initModel =
{ something = "Hello"
, somethingElse = "World"
, items =
Dict.fromList
[ ( "APPLE", Item "apple" 1 )
, ( "ORANGE", Item "orange" 2 )
]
, selectedItem = Nothing
}
type Msg
= SelectItem String
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
SelectItem itemStringId ->
{ model | selectedItem = Just itemStringId } ! []
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment