Search code examples
elm

How to update the model in the dynamically generated view?


import Browser
import Html exposing (Html, button, div, text)
import Html.Attributes exposing (disabled)
import Html.Events exposing (onClick)


main =
    Browser.sandbox
        { init =
            { count = 0
            , node = text ""
            , inactive = False
            }
        , update = update
        , view = view
        }


type Msg
    = Increment
    | AddNode


update msg model =
    case msg of
        Increment ->
            Debug.log "count"
                { model
                    | count = model.count + 1
                }

        AddNode ->
            let
                viewDynamic =
                    div []
                        [ text (String.fromInt model.count) ]
            in
            { model
                | node =
                    div []
                        [ button [ onClick Increment ] [ text "+" ]
                        , viewDynamic
                        ]
                , inactive = True
            }


view model =
    let
        viewStatic =
            button
                [ disabled model.inactive
                , onClick AddNode
                ]
                [ text "new" ]
    in
    div []
        [ viewStatic
        , model.node
        ]

Above, the initial static view can react to the update of model.inactive, but the subsequent dynamic view fails to update model.count. How to ideally achieve it?


Solution

  • Solved ideally thanks to the hints from @glennsl .

    import Browser
    import Html exposing (Html, button, div, text)
    import Html.Attributes exposing (disabled)
    import Html.Events exposing (onClick)
    
    
    main =
        Browser.sandbox
            { init =
                { count = 0
                , added = False
                , inactive = False
                }
            , update = update
            , view = view
            }
    
    
    type Msg
        = Increment
        | AddNode
    
    
    update msg model =
        case msg of
            Increment ->
                { model | count = model.count + 1 }
    
            AddNode ->
                { model | inactive = True, added = True }
    
    
    view model =
        let
            viewStatic =
                button
                    [ disabled model.inactive
                    , onClick AddNode
                    ]
                    [ text "new" ]
    
            viewDynamic =
                div []
                    [ text (String.fromInt model.count) ]
        in
        div []
            [ viewStatic
            , if model.added then
                div []
                    [ button [ onClick Increment ] [ text "+" ]
                    , viewDynamic
                    ]
    
              else
                text ""
            ]