Renamed to FabienHenon/app-object. It is published under that name, and new versions come out there.
Versions published as calions-app/app-object still install under that name. 1 version of 1 come from the new location (see their notes).
Rerouted (renamed, verified). The GitHub user or repository was renamed. The tag is still there, at the new name. The Lamdera package server serves a copy recovered from https://github.com/FabienHenon/app-object.
What we checked: The repo moved to github.com/FabienHenon/app-object. Rebuilt with git archive from commit c638222af4ec of https://github.com/FabienHenon/app-object (zip prefix calions-app-app-object-c638222/, America/Los_Angeles times): the zip is byte-identical to the one package.elm-lang.org recorded, SHA-1 7a2562ba9f263025cfb37d6bc411346d5d6c2c5a.
The Lamdera compiler uses this copy and prints a one-line notice saying so. elm itself fails to download this version.
Details · package.elm-lang.org's zip: https://github.com/calions-app/app-object/zipball/1.0.0/
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:
You should start by defining what is your global state and what are your global messages.
Also, you could create an alias of AppObject which is resolved by your own appData and appMsg:
type alias MyAppObject model msg =
AppObject.AppObject Data AppMsg model msg
type alias Data =
{ isModalOpen : Bool
}
type AppMsg
= ToggleModal BoolIn your components each of your functions (init, update, view, subscriptions) should take your appData as parameter and your side effect functions (init, update)
must return an AppObject.
type Msg
= OnClick Bool
type alias Model =
()
init : Data -> MyAppObject Model Msg
init data =
AppObject.init data ()
update : Msg -> Data -> Model -> MyAppObject Model Msg
update msg data model =
case msg of
OnClick isModalOpen ->
AppObject.init data model
|> AppObject.batchAppCmd (Task.perform AppData.ToggleModal (Task.succeed (not isModalOpen)))This way you can read the values in your appData model, everywhere in your application. For instance, you could know wether or not the modal is opened:
view : Data -> Model -> Html Msg
view data model =
div []
[ button [ onClick (OnClick (AppData.isModalOpen data)) ]
[ if AppData.isModalOpen data then
text "Close Modal"
else
text "Open Modal"
]
]In your root component you should keep the appData in your state:
type alias Model =
{ component : Component.Model
, data : Data
}You must also:
appData returned by your component (this is new)type Msg
= ComponentMsg Component.Msg
| AppMsgHandler AppMsg
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ComponentMsg msg_ ->
AppObject.init model.data model.component
|> AppObject.andThen (Component.update msg_)
|> AppObject.mapMsg ComponentMsg
|> AppObject.mapModel (\component -> { model | component = component })
|> AppObject.run mergeAppData AppMsgHandler
AppMsgHandler (AppData.ToggleModal isModalOpen) ->
AppObject.init (AppData.setModalOpen isModalOpen model.data) model
|> AppObject.run mergeAppData AppMsgHandler
mergeAppData : Data -> Model -> Model
mergeAppData data model =
{ model | data = data }To run the examples go to the examples directory, install dependencies and run elm reactor:
> cd examples/
> elm reactor