The AppObject
is an object that encapsulates the Model
and Cmd Msg
of a component (returned in side effect functions like init
or update
) plus and appData
object and a Cmd appMsg
.
These new elements are a model and commands related to the entire application.
Let's say for instance that you have a component that does something (whatever) and that needs to open a modal, or set the connected user, or set the user language of the application, ... All of these states/effects are related to the application, not to the component. Indeed, the component itself can't open a modal because it's the application's responsibility. Also, the component could save the connected user to its own state, but it's a data the entire application would like to know about and with the classic architecture of elm apps it's not possible for a component to tell the app that it should update its state.
To make it simpler: a component can't change the state of its parent component and can't send commands with its parent's messages.
This is what AppObject
is for, it allows you to:
AppObject
is the object you should return from your side effect functions (init
, update
) in your components.
appData
refers to the model you want to be global to your application. This model is usualy stored in your root stateappMsg
refers to the msg
type you want to be global to your application. This msg
is usually handle in your root update
functionmodel
refers to the model of your current componentmsg
refers to the msg
type of your current componentI suggest your create a module that defines your appData
model and your appMsg
message type, and you define a type alias
of your own AppObject
with
the appData
and appMsg
set :
type alias MyAppObject model msg =
AppObject.AppObject Data AppMsg model msg
type alias Data =
{ isModalOpen : Bool
}
type AppMsg
= ToggleModal Bool
init : appData -> model -> AppObject appData appMsg model msg
Creates a new AppObject
from the appData
and your component's model
batchCmd : Platform.Cmd.Cmd msg -> AppObject appData appMsg model msg -> AppObject appData appMsg model msg
Adds a new component's command to this AppObject
batchAppCmd : Platform.Cmd.Cmd appMsg -> AppObject appData appMsg model msg -> AppObject appData appMsg model msg
Adds a new global command to this AppObject
batchCmdWithModel : (model -> ( model, Platform.Cmd.Cmd msg )) -> AppObject appData appMsg model msg -> AppObject appData appMsg model msg
Adds a new component's command to this AppObject
? The model is passed as parameter
batchAppCmdWithModel : (model -> ( model, Platform.Cmd.Cmd appMsg )) -> AppObject appData appMsg model msg -> AppObject appData appMsg model msg
Adds a new global command to this AppObject
. The model is passed as parameter
map : (modelA -> modelB) -> (appDataA -> appDataB) -> (msgA -> msgB) -> (appMsgA -> appMsgB) -> AppObject appDataA appMsgA modelA msgA -> AppObject appDataB appMsgB modelB msgB
Maps your AppObject
to change the types of appData
, appMsg
, model
and msg
mapAppData : (a -> appData) -> AppObject a appMsg model msg -> AppObject appData appMsg model msg
Maps only your appData
mapAppMsg : (a -> appMsg) -> AppObject appData a model msg -> AppObject appData appMsg model msg
Maps only your appMsg
mapModel : (a -> model) -> AppObject appData appMsg a msg -> AppObject appData appMsg model msg
Maps only your model
mapMsg : (a -> msg) -> AppObject appData appMsg model a -> AppObject appData appMsg model msg
Maps only your msg
merge : (modelB -> modelA -> modelC) -> (appDataB -> appDataA -> appDataC) -> (msgA -> msgC) -> (msgB -> msgC) -> (appMsgA -> appMsgC) -> (appMsgB -> appMsgC) -> AppObject appDataA appMsgA modelA msgA -> AppObject appDataB appMsgB modelB msgB -> AppObject appDataC appMsgC modelC msgC
Merges 2 AppObject
s together. You provide the functions used to:
model
appData
msg
appMsg
foldl : (a -> AppObject appData appMsg model msg -> AppObject appData appMsg model msg) -> List a -> AppObject appData appMsg model msg -> AppObject appData appMsg model msg
Reducer that allows you to update or create an AppObject
for each element of a list
andThen : (appDataA -> modelA -> AppObject appDataB appMsg modelB msg) -> AppObject appDataA appMsg modelA msg -> AppObject appDataB appMsg modelB msg
Allows you to create a new AppObject
from an existing one, using the appData
and the model
. The new Cmd appMsg
and Cmd msg
will be batched to the
existing ones
run : (appData -> model -> model) -> (appMsg -> msg) -> AppObject appData appMsg model msg -> ( model, Platform.Cmd.Cmd msg )
Executes your AppObject
. That means that you will create a ( model, Cmd msg )
tuple from an AppObject
, this allows you to run your side effects and model updates
in your root update
and init
functions