elm-mdl/src/Material.elm

179 lines
4.8 KiB
Elm
Raw Normal View History

2016-04-06 13:28:37 +00:00
module Material
( Model, model
, Action, update
)
where
2016-03-14 09:42:49 +00:00
2016-04-06 13:28:37 +00:00
{-|
Material Design component library for Elm based on Google's
2016-03-14 09:42:49 +00:00
[Material Design Lite](https://www.getmdl.io/).
2016-04-06 13:28:37 +00:00
Click
[here](https://debois.github.io/elm-mdl/)
for a live demo.
2016-03-19 22:47:21 +00:00
2016-04-06 13:28:37 +00:00
# Component model
2016-04-06 13:28:37 +00:00
The component model of the library is simply the Elm Architecture, e.g.,
each component has Model, Action, view, and update. A minimal example using
this library in plain Elm Architecture can be found
[here](https://github.com/debois/elm-mdl/blob/master/examples/Component-EA.elm).
2016-03-14 09:42:49 +00:00
2016-04-06 13:28:37 +00:00
Nesting large amounts of components in the Elm Architecture is somewhat
unwieldy because of the large amount of boilerplate one has to write. This
library includes "component support", for getting rid of most of that
boilerplate. A minimal example using component support is
[here](http://github.com/debois/elm-mdl/blob/master/examples/Component.elm).
2016-03-14 09:42:49 +00:00
2016-04-06 13:28:37 +00:00
It is important to note that component support lives __within__ the Elm
architecture; it is not an alternative architecture.
2016-03-14 09:42:49 +00:00
2016-04-06 13:28:37 +00:00
# Getting started
2016-03-19 22:47:21 +00:00
2016-04-06 13:28:37 +00:00
The easiest way to get started is to start with one of the minimal examples above.
We recommend going with the library's component support rather than working
directly in plain Elm Architecture.
2016-03-14 09:42:49 +00:00
2016-04-06 13:28:37 +00:00
# This module
2016-03-14 09:42:49 +00:00
2016-04-06 13:28:37 +00:00
This module contains only convenience functions for working with nested
components in the Elm architecture. A minimal example using this library
with component support can be found
[here](http://github.com/debois/elm-mdl/blob/master/examples/Component.elm).
We encourage you to use the library in this fashion.
2016-03-14 09:42:49 +00:00
2016-04-06 13:28:37 +00:00
All examples in this subsection is from the
[above minimal example](http://github.com/debois/elm-mdl/blob/master/examples/Component.elm)
2016-03-14 09:42:49 +00:00
2016-04-06 13:28:37 +00:00
Here is how you use component support in general. First, boilerplate.
2016-03-14 09:42:49 +00:00
2016-04-06 13:28:37 +00:00
1. Include `Material`:
`import Material`
2016-03-14 09:42:49 +00:00
2016-04-06 13:28:37 +00:00
2. Add a model container Material components to your model:
2016-03-14 09:42:49 +00:00
2016-04-06 13:28:37 +00:00
type alias Model =
{ ...
, mdl : Material.Model
}
2016-03-14 09:42:49 +00:00
2016-04-06 13:28:37 +00:00
model : Model =
{ ...
, mdl = Material.model
}
2016-03-14 09:42:49 +00:00
2016-04-06 13:28:37 +00:00
3. Add an action for Material components.
2016-04-06 13:28:37 +00:00
type Action =
...
| MDL (Material.Action Action)
4. Handle that action in your update function as follows:
update action model =
case action of
...
MDL action' ->
let (mdl', fx) =
Material.update MDL action' model.mdl
in
( { model | mdl = mdl' } , fx )
Next, make the component instances you need. Do this in the View section of your
source file. Let's say you need a textfield for name entry, and you'd like to
be notifed whenever the field changes value through your own NameChanged action:
import Material.Textfield as Textfield
...
type Action =
...
| NameChanged String
...
update action model =
case action of
...
NameChanged name ->
-- Do whatever you need to do.
2016-03-17 12:31:43 +00:00
2016-04-06 13:28:37 +00:00
...
2016-03-17 12:31:43 +00:00
2016-04-06 13:28:37 +00:00
nameInput : Textfield.Instance Material.Model Action
nameInput =
Textfield.instance 2 MDL Textfield.model
[ Textfield.fwdInput NameChanged ]
2016-03-17 12:31:43 +00:00
2016-04-06 13:28:37 +00:00
view addr model =
...
nameInput.view addr model.mdl
The win relative to using plain Elm Architecture is that adding a component
neither requires you to update your model, your Actions, nor your update function.
(As in the above example, you will frequently have to update the latter two anyway,
but now it's not boilerplate, its "business logic".)
## Optimising for size
Using this module will force all elm-mdl components to be built and included in
your application. If this is unacceptable, you can custom-build a version of this
module that uses only the components you need. To do so, you need to re-implement
the present module, modifying the values `model` and `Model`. The module source
can be found
[here](https://github.com/debois/elm-mdl/blob/master/src/Material.elm).
You do not need to re-build the entire elm-mdl library; simply copy the
source of this module, give it a new name, modify as itMatendicated above, then use
your modified module rather than this one.
@docs Model, model, Action, update
2016-03-17 12:31:43 +00:00
-}
2016-04-06 13:28:37 +00:00
import Dict
import Effects exposing (Effects)
2016-03-17 12:31:43 +00:00
2016-04-06 13:28:37 +00:00
import Material.Button as Button
import Material.Textfield as Textfield
import Material.Component as Component exposing (Indexed)
{-| Model encompassing all Material components.
2016-03-17 12:31:43 +00:00
-}
2016-04-06 13:28:37 +00:00
type alias Model =
{ button : Indexed Button.Model
, textfield : Indexed Textfield.Model
}
2016-03-17 12:31:43 +00:00
2016-04-06 13:28:37 +00:00
{-| Initial model.
-}
model : Model
model =
{ button = Dict.empty
, textfield = Dict.empty
}
2016-03-17 12:31:43 +00:00
2016-04-06 13:28:37 +00:00
{-| Action encompassing actions of all Material components.
2016-03-17 12:31:43 +00:00
-}
2016-04-06 13:28:37 +00:00
type alias Action action =
Component.Action Model action
{-| Update function for the above Action.
2016-03-17 12:31:43 +00:00
-}
2016-04-06 13:28:37 +00:00
update :
(Action action -> action)
-> (Action action)
-> Model
-> (Model, Effects action)
update =
Component.update