uncover-co / elm-submodules / SubModule

This module is used for plugging submodules into a host module. If you're working on the submodule itself, check out SubCmd.

initWithEffect : { toMsg : subMsg -> msg, effectToMsg : subEffect -> msg } -> ( subModel, SubCmd subMsg subEffect ) -> ( subModel, ( model, Platform.Cmd.Cmd msg ) -> ( model, Platform.Cmd.Cmd msg ) )

Enables you to initialize submodules that can send effects.

let
    -- This submodule can't send effects
    ( widget, initWidget ) =
        Widget.init
            |> SubModule.init
                { toMsg = GotWidgetMsg
                }

    -- But this one can!
    ( superWidget, initSuperWidget ) =
        SuperWidget.init
            |> SubModule.initWithEffect
                { toMsg = GotSuperWidgetMsg
                , effectToMsg = GotSuperWidgetEffect
                }
in
( { widget = widget
  , superWidget = superWidget
  }
, Cmd.none
)
    |> initWidget
    |> initSuperWidget

updateWithEffect : { toModel : subModel -> model, toMsg : subMsg -> msg, effectToMsg : subEffect -> msg } -> ( subModel, SubCmd subMsg subEffect ) -> ( model, Platform.Cmd.Cmd msg )

Enables you to handle the updates of submodules that can send effects.

type Model =
    { widget : Widget.Model
    , valueFromWidget : Maybe String
    }

type Msg
    = GotWidgetMsg Widget.Msg
    | GotWidgetEffect Widget.Effect

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        GotWidgetMsg widgetMsg ->
            Widget.update widgetMsg model.widget
                |> SubModule.updateWithEffect
                    { toMsg = GotWidgetMsg
                    , effectToMsg = GotWidgetEffect
                    , toModel =
                        \widget -> { model | widget = widget }
                    }

        GotWidgetEffect widgetEffect ->
            case widgetEffect of
                Widget.SendValue value ->
                    ( { model | valueFromWidget = Just value }
                    , Cmd.none
                    )

Modules without effect

We also provide a few functions to help you deal with modules that can't send effects so you have a similar API across your host module. Note that the same could be achieved without this package at all.

init : { toMsg : subMsg -> msg } -> ( subModel, Platform.Cmd.Cmd subMsg ) -> ( subModel, ( model, Platform.Cmd.Cmd msg ) -> ( model, Platform.Cmd.Cmd msg ) )

Enables you to initialize multiple submodules that cannot send effects.

let
    ( widget, initWidget ) =
        Widget.init
            |> SubModule.init
                { toMsg = GotWidgetMsg
                }

    ( otherWidget, initOtherWidget ) =
        OtherWidget.init
            |> SubModule.init
                { toMsg = GotOtherWidgetMsg
                }
in
( { widget = widget, otherWidget = otherWidget }, Cmd.none )
    |> initWidget
    |> initOtherWidget

update : { toModel : subModel -> model, toMsg : subMsg -> msg } -> ( subModel, Platform.Cmd.Cmd subMsg ) -> ( model, Platform.Cmd.Cmd msg )

Enables you to handle the updates of submodules that cannot send effects.

type Msg
    = GotWidgetMsg Widget.Msg
    | ...

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        GotWidgetMsg widgetMsg ->
            Widget.update widgetMsg model.widget
                |> SubModule.update
                    { toMsg = GotWidgetMsg
                    , toModel = \widget -> { model | widget = widget }
                    }
        ...