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-03-15 16:35:34 +00:00
|
|
|
|
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-03-15 16:35:34 +00:00
|
|
|
|
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
|
2016-04-06 18:16:54 +00:00
|
|
|
import Material.Snackbar as Snackbar
|
2016-04-06 13:28:37 +00:00
|
|
|
import Material.Component as Component exposing (Indexed)
|
|
|
|
|
|
|
|
|
|
|
|
{-| Model encompassing all Material components.
|
2016-03-17 12:31:43 +00:00
|
|
|
-}
|
2016-04-06 18:16:54 +00:00
|
|
|
type alias Model a =
|
2016-04-06 13:28:37 +00:00
|
|
|
{ button : Indexed Button.Model
|
|
|
|
, textfield : Indexed Textfield.Model
|
2016-04-06 18:16:54 +00:00
|
|
|
, snackbar : Indexed (Snackbar.Model a)
|
2016-04-06 13:28:37 +00:00
|
|
|
}
|
|
|
|
|
2016-03-17 12:31:43 +00:00
|
|
|
|
2016-04-06 13:28:37 +00:00
|
|
|
{-| Initial model.
|
|
|
|
-}
|
2016-04-06 18:16:54 +00:00
|
|
|
model : Model a
|
2016-04-06 13:28:37 +00:00
|
|
|
model =
|
|
|
|
{ button = Dict.empty
|
|
|
|
, textfield = Dict.empty
|
2016-04-06 18:16:54 +00:00
|
|
|
, snackbar = Dict.empty
|
2016-04-06 13:28:37 +00:00
|
|
|
}
|
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 =
|
2016-04-06 18:16:54 +00:00
|
|
|
Component.Action (Model action) action
|
2016-04-06 13:28:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
{-| 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)
|
2016-04-06 18:16:54 +00:00
|
|
|
-> Action action
|
|
|
|
-> Model action
|
|
|
|
-> (Model action, Effects action)
|
2016-04-06 13:28:37 +00:00
|
|
|
update =
|
|
|
|
Component.update
|