elm-spa/README.md

196 lines
3.4 KiB
Markdown
Raw Normal View History

2019-10-05 01:16:02 +03:00
# ryannhg/elm-app
> a way to build single page apps with Elm.
## try it out
```
elm install ryannhg/elm-app
```
## quick overview
this package is a wrapper around Elm's `Browser.application`, adding in page transitions and utilities for adding in new pages and routes.
here's what it looks like to use it:
### src/Main.elm
2019-10-05 01:18:12 +03:00
> Uses `Application.create`
2019-10-05 01:16:02 +03:00
2019-10-05 01:18:12 +03:00
This is the entrypoint to the app, it imports a few things:
2019-10-05 01:16:02 +03:00
2019-10-05 01:18:12 +03:00
- `Application` - (this package)
2019-10-05 01:16:02 +03:00
- `App` - the top level `Model`, `Msg`, `init`, `update`, `subscriptions`, and `view`
2019-10-05 01:18:12 +03:00
- `Context` - the shared state between pages.
- `Route` - the routes for your application
- `Flags` - the initial JSON sent into the app
2019-10-05 01:16:02 +03:00
```elm
module Main exposing (main)
import Application exposing (Application)
import App
import Context
import Route
import Flags exposing (Flags)
main : Application Flags Context.Model Context.Msg App.Model App.Msg
main =
Application.create
{ transition = 300
, toRoute = Route.fromUrl
, title = Route.title
, context =
{ init = Context.init
, update = Context.update
, view = Context.view
, subscriptions = Context.subscriptions
}
, page =
{ init = App.init
, update = App.update
, view = App.view
, subscriptions = App.subscriptions
}
}
```
### src/Pages/Homepage.elm
2019-10-05 01:18:12 +03:00
> uses `Application.Page.static`
2019-10-05 01:16:02 +03:00
The homepage is static, so it's just a `view`:
```elm
module Pages.Homepage exposing (view)
import Html exposing (Html)
view : Html Never
view =
Html.text "Homepage!"
```
### src/Pages/Counter.elm
2019-10-05 01:18:12 +03:00
> uses `Application.Page.Sandbox`
2019-10-05 01:16:02 +03:00
The counter page doesn't have any side effects:
```elm
module Pages.Counter exposing (Model, Msg, init, update, view)
import Html exposing (..)
import Html.Events as Events
type alias Model =
{ counter : Int
}
type Msg
= Increment
| Decrement
init : Model
init =
{ counter = 0
}
update : Msg -> Model -> Model
update msg model =
case msg of
Decrement ->
{ model | counter = model.counter - 1 }
Increment ->
{ model | counter = model.counter + 1 }
view : Model -> Html Msg
view model =
div []
[ button [ Events.onClick Decrement ] [ text "-" ]
, text (String.fromInt model.counter)
, button [ Events.onClick Increment ] [ text "+" ]
]
```
### src/Pages/Random.elm
2019-10-05 01:18:12 +03:00
> uses `Application.Page.element`
2019-10-05 01:16:02 +03:00
The random page doesn't need to update the context of the application:
```elm
module Pages.Random exposing
( Model
, Msg
, init
, subscriptions
, update
, view
)
import Flags exposing (Flags)
import Html exposing (..)
import Html.Events as Events
import Random
type alias Model =
2019-10-05 01:18:12 +03:00
{ roll : Maybe Int
}
2019-10-05 01:16:02 +03:00
type Msg
2019-10-05 01:18:12 +03:00
= Roll
| GotOutcome Int
2019-10-05 01:16:02 +03:00
init : Flags -> ( Model, Cmd Msg )
init _ =
( { roll = Nothing }
, Cmd.none
)
rollDice : Model -> ( Model, Cmd Msg )
rollDice model =
( model
, Random.generate GotOutcome (Random.int 1 6)
)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Roll ->
rollDice model
GotOutcome value ->
( { model | roll = Just value }
, Cmd.none
)
view : Model -> Html Msg
view model =
div []
[ button [ Events.onClick Roll ] [ text "Roll" ]
, p []
2019-10-05 01:18:12 +03:00
( case model.roll of
2019-10-05 01:16:02 +03:00
Just roll ->
2019-10-05 01:18:12 +03:00
[ text (String.fromInt roll) ]
2019-10-05 01:16:02 +03:00
Nothing ->
2019-10-05 01:18:12 +03:00
[]
)
2019-10-05 01:16:02 +03:00
]
subscriptions : Model -> Sub Msg
subscriptions model =
2019-10-05 01:18:12 +03:00
Sub.none
2019-10-05 01:16:02 +03:00
```