How to create a general update function for a nested entry in Elm

In Elm, I have a model with nested attributes like:

model =
  { name = ""
  , disruptedFields =
    { advertising =
      { name = "Advertising"
      , checked = False
      }
    , travel =
      { name = "Travel"
      , checked = False
      }
    , utilities =
      { name = "Utilities"
      , checked = False
      }
    }
  }

disruptedFieldscontains a list of values ​​for flags. When I click on this checkbox, I am sending an update message to UpdateDisruptedField, which currently looks like this:

UpdateDisruptedField value ->
  let
    fieldCollection = model.disruptedFields
    field = fieldCollection.advertising
  in
    { model | disruptedFields =
      { fieldCollection | advertising =
        { field | checked = (not value) }
      }
    }

My update function is hardcoded to model.disruptedField.advertisingin fieldand variables advertising. This works for me, but I'm stuck making the function common.

How to pass record to UpdateDisruptedField so that I can make it shared?

+4
source share
2 answers

This is a common problem for Elm applications with many input fields. There are two approaches to creating a common update function to reduce code repetition.

  • , case checkboxType of . , , .

  • .

, - .

, :

module Main exposing (..)

import Html exposing (div, input, text, label)
import Html.App exposing (beginnerProgram)
import Html.Events exposing (onCheck)
import Html.Attributes exposing (type', checked)
import Dict


(=>) : a -> b -> ( a, b )
(=>) a b =
    ( a, b )


main =
    beginnerProgram { model = model, view = view, update = update }


model =
    { name = ""
    , disruptedFields =
        Dict.fromList
            [ "advertising"
                => { name = "Advertising"
                   , checked = False
                   }
            , "travel"
                => { name = "Travel"
                   , checked = False
                   }
            , "utilities"
                => { name = "Utilities"
                   , checked = False
                   }
            ]
    }


type Msg
    = Check String Bool


view model =
    let
        checkbox ( key, data ) =
            label []
                [ text data.name
                , input
                    [ type' "checkbox"
                    , checked data.checked
                    , onCheck (Check key)
                    ]
                    []
                ]
    in
        div []
            (model.disruptedFields
                |> Dict.toList
                |> List.map checkbox
            )


update msg model =
    case msg of
        Check checkboxId checked ->
            let
                updateRecord =
                    Maybe.map (\checkboxData -> { checkboxData | checked = checked })

                disruptedFieldsUpdated =
                    Dict.update checkboxId
                        updateRecord
                        model.disruptedFields
            in
                { model | disruptedFields = disruptedFieldsUpdated }

, =>, Tuples .

disruptedFields , String, .

+6
+1

Source: https://habr.com/ru/post/1648883/


All Articles