abinayasudhir / outmessage / OutMessage

Note: This library is opinionated. The usage of an OutMsg is a technique to extend The Elm Architecture (TEA) to support child-parent communication. The README covers the design.

The OutMsg pattern has two components:

OutMsg values can be captured in the parent's update function, and handled there by interpretOutMsg. The basic pattern can be extended to return multiple OutMsg using List or to optionally return no OutMsg using Maybe.

Evaluators

evaluate : (outMsg -> model -> ( model, Platform.Cmd.Cmd msg )) -> ( model, Platform.Cmd.Cmd msg, outMsg ) -> ( model, Platform.Cmd.Cmd msg )

Turn an OutMsg value into commands and model changes.

The arguments are:

Example usage:

-- in update : Msg -> Model -> (Model, Cmd Msg)
-- assuming interpretOutMsg : OutMsg -> Model -> (Model, Cmd Msg)
-- ChildComponentModule.update
--       : ChildMsg
--       -> ChildModel -> (ChildModel, Cmd ChildMsg, OutMsg)
ChildComponentMessageWrapper childMsg ->
    ChildComponentModule.update childMsg model.child
        -- update the model with the new child component
        |> OutMessage.mapComponent
            (\newChild -> { model | child = newChild }
        -- convert child cmd to parent cmd
        |> OutMessage.mapCmd ChildComponentMessageWrapper
        -- apply outmsg changes
        |> OutMessage.evaluate interpretOutMsg

evaluateMaybe : (outMsg -> model -> ( model, Platform.Cmd.Cmd msg )) -> Platform.Cmd.Cmd msg -> ( model, Platform.Cmd.Cmd msg, Maybe outMsg ) -> ( model, Platform.Cmd.Cmd msg )

Turn a Maybe OutMsg into effects and model changes.

Has a third argument for a default command that is used when OutMsg is Nothing.

evaluateList : (outMsg -> model -> ( model, Platform.Cmd.Cmd msg )) -> ( model, Platform.Cmd.Cmd msg, List outMsg ) -> ( model, Platform.Cmd.Cmd msg )

Turn a List OutMsg into effects and model changes.

Takes care of threading the state. When interpreting an OutMsg changes the model, the updated model will be used for subsequent interpretations of OutMsgs. Cmds are accumulated and batched.

mapComponent : (childComponent -> a) -> ( childComponent, b, c ) -> ( a, b, c )

Apply a function over the updated child component.

mapCmd : (childmsg -> parentmsg) -> ( a, Platform.Cmd.Cmd childmsg, c ) -> ( a, Platform.Cmd.Cmd parentmsg, c )

Apply a function over the Msg from the child.

addOutMsg : outMsg -> ( model, Platform.Cmd.Cmd msg ) -> ( model, Platform.Cmd.Cmd msg, outMsg )

Add an outmessage to the normal type that update has. Handy to use in a pipe:

( { model | a = 1 }, Cmd.none )
    |> addOutMsg Nothing

toNested : ( a, b, c ) -> ( ( a, b ), c )

Helper to split the OutMsg from the normal type that update has.

The functions fst and snd can now be used, which can be handy.

wrap : (outmsg -> model -> ( model, Platform.Cmd.Cmd msg )) -> outmsg -> State model (Platform.Cmd.Cmd msg)

Embed a function into State

run : Platform.Cmd.Cmd msg -> model -> State model (Platform.Cmd.Cmd msg) -> ( model, Platform.Cmd.Cmd msg )

Evaluate a State model (Cmd msg) given a model, and commands to prepend.

wrap interpretOutMsg myOutMsg
    |> run Cmd.none myModel