mirror of
https://github.com/ryannhg/elm-spa.git
synced 2024-11-22 09:44:55 +03:00
add page section to readme
This commit is contained in:
parent
b910d88952
commit
d33eeb163c
@ -501,3 +501,238 @@ toHref route =
|
|||||||
```
|
```
|
||||||
|
|
||||||
This function allows all our URLs to be handled in one place in the application.
|
This function allows all our URLs to be handled in one place in the application.
|
||||||
|
|
||||||
|
|
||||||
|
## src/Pages.elm
|
||||||
|
|
||||||
|
Now we are ready to take a look at how `ryannhg/elm-spa` allows us to compose together our pages.
|
||||||
|
|
||||||
|
Let's define the top-level `Pages` module that handles initializing, updating, viewing, and receiving subscriptions from the current page.
|
||||||
|
|
||||||
|
```elm
|
||||||
|
import Pages exposing
|
||||||
|
( Model
|
||||||
|
, Msg
|
||||||
|
, init
|
||||||
|
, update
|
||||||
|
, view
|
||||||
|
, subscriptions
|
||||||
|
)
|
||||||
|
|
||||||
|
import Global
|
||||||
|
import Document exposing (Document)
|
||||||
|
import Page exposing (Page)
|
||||||
|
import Pages.Top as Top
|
||||||
|
import Pages.AboutUs as AboutUs
|
||||||
|
import Pages.Posts as Posts
|
||||||
|
import Pages.Post as Post
|
||||||
|
import Pages.NotFound as NotFound
|
||||||
|
import Route
|
||||||
|
import Url exposing (Url)
|
||||||
|
```
|
||||||
|
|
||||||
|
### model, msg, and upgraded pages
|
||||||
|
|
||||||
|
The user can only be on one page at a time, so we use a custom type to represent which page we are currently viewing.
|
||||||
|
|
||||||
|
```elm
|
||||||
|
type Model
|
||||||
|
= Top_Model Top.Model
|
||||||
|
| AboutUs_Model AboutUs.Model
|
||||||
|
| Posts_Model Posts.Model
|
||||||
|
| Post_Model Post.Model
|
||||||
|
| NotFound_Model NotFound.Model
|
||||||
|
```
|
||||||
|
|
||||||
|
Additionally, messages could be sent from any one of the five pages.
|
||||||
|
|
||||||
|
```elm
|
||||||
|
type Msg
|
||||||
|
= Top_Msg Top.Msg
|
||||||
|
| AboutUs_Msg AboutUs.Msg
|
||||||
|
| Posts_Msg Posts.Msg
|
||||||
|
| Post_Msg Post.Msg
|
||||||
|
| NotFound_Msg NotFound.Msg
|
||||||
|
```
|
||||||
|
|
||||||
|
What's great about the custom types above? Each variant we created (like `Top_Model` and `Top_Msg`) are actually functions with signatures like this:
|
||||||
|
|
||||||
|
```elm
|
||||||
|
Top_Model : Top.Model -> Model
|
||||||
|
Top_Msg : Top.Msg -> Msg
|
||||||
|
|
||||||
|
AboutUs_Model : AboutUs.Model -> Model
|
||||||
|
AboutUs_Msg : AboutUs.Msg -> Msg
|
||||||
|
|
||||||
|
Posts_Model : Posts.Model -> Model
|
||||||
|
Posts_Msg : Posts.Msg -> Msg
|
||||||
|
|
||||||
|
-- ... same for Post, NotFound
|
||||||
|
```
|
||||||
|
|
||||||
|
What that means is if I call `Top_Model` with a `Top.Model`, I'll get a `Model` back. The same goes for giving `About_Msg` an `AboutUs.Msg`!
|
||||||
|
|
||||||
|
All these varaiants are functions that tell each page how they can upgrade to the shared `Model` and `Msg` types we just defined.
|
||||||
|
|
||||||
|
With `elm-spa`, we want to "upgrade our pages" using these variants!
|
||||||
|
|
||||||
|
```elm
|
||||||
|
type alias Upgraded pageFlags pageModel pageMsg =
|
||||||
|
{ init :
|
||||||
|
pageFlags
|
||||||
|
-> Global.Model
|
||||||
|
-> ( Model, Cmd Msg, Cmd Global.Msg )
|
||||||
|
, update :
|
||||||
|
pageMsg
|
||||||
|
-> pageModel
|
||||||
|
-> Global.Model
|
||||||
|
-> ( Model, Cmd Msg, Cmd Global.Msg )
|
||||||
|
, bundle :
|
||||||
|
pageModel
|
||||||
|
-> { view : Document Msg
|
||||||
|
, subscriptions : Sub Msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Our goal now is to create an `Upgraded` for each page in our application. An "upgraded page" has all the information we need to return the correct values, no matter which page we are using.
|
||||||
|
|
||||||
|
It returns a record with three functions. Each of these functions take page-specific input and output the **same type of value**.
|
||||||
|
|
||||||
|
Returning the same type is what allows us to easily create the top-level `init`, `update`, `view`, and `subscriptions` functions.
|
||||||
|
|
||||||
|
Fortunately, if we provide `Page.upgrade` with those variant functions and a page, `elm-spa` handles the logic for us!
|
||||||
|
|
||||||
|
```elm
|
||||||
|
pages :
|
||||||
|
{ top : Upgraded Top.Flags Top.Model Top.Msg
|
||||||
|
, aboutUs : Upgraded AboutUs.Flags AboutUs.Model AboutUs.Msg
|
||||||
|
, posts : Upgraded Posts.Flags Posts.Model Posts.Msg
|
||||||
|
, post : Upgraded Post.Flags Post.Model Post.Msg
|
||||||
|
, notFound : Upgraded NotFound.Flags NotFound.Model NotFound.Msg
|
||||||
|
}
|
||||||
|
pages =
|
||||||
|
{ top = Top.page |> Page.upgrade Top_Model Top_Msg
|
||||||
|
, aboutUs = AboutUs.page |> Page.upgrade AboutUs_Model AboutUs_Msg
|
||||||
|
, posts = Posts.page |> Page.upgrade Posts_Model Posts_Msg
|
||||||
|
, post = Post.page |> Page.upgrade Post_Model Post_Msg
|
||||||
|
, notFound = NotFound.page |> Page.upgrade NotFound_Model NotFound_Msg
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
It's okay if this doesn't make sense yet, let's look at how we use the upgraded `pages` values to create our top-level `Pages` functions:
|
||||||
|
|
||||||
|
### init
|
||||||
|
|
||||||
|
```elm
|
||||||
|
init : Url -> Global.Model -> ( Model, Cmd Msg, Cmd Global.Msg )
|
||||||
|
init url =
|
||||||
|
case Route.fromUrl url of
|
||||||
|
Route.Top ->
|
||||||
|
pages.top.init ()
|
||||||
|
|
||||||
|
Route.AboutUs ->
|
||||||
|
pages.aboutUs.init ()
|
||||||
|
|
||||||
|
Route.Posts ->
|
||||||
|
pages.posts.init ()
|
||||||
|
|
||||||
|
Route.Post id ->
|
||||||
|
pages.post.init id
|
||||||
|
|
||||||
|
Route.NotFound ->
|
||||||
|
pages.notFound.init ()
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### update
|
||||||
|
|
||||||
|
```elm
|
||||||
|
update : Msg -> Model -> Global.Model -> ( Model, Cmd Msg, Cmd Global.Msg )
|
||||||
|
update msg_ model_ =
|
||||||
|
case ( msg_, model_ ) of
|
||||||
|
( Top_Msg msg, Top_Model model ) ->
|
||||||
|
pages.top.update msg model
|
||||||
|
|
||||||
|
( AboutUs_Msg msg, AboutUs_Model model ) ->
|
||||||
|
pages.aboutUs.update msg model
|
||||||
|
|
||||||
|
( Posts_Msg msg, Posts_Model model ) ->
|
||||||
|
pages.posts.update msg model
|
||||||
|
|
||||||
|
( Post_Msg msg, Post_Model model ) ->
|
||||||
|
pages.post.update msg model
|
||||||
|
|
||||||
|
( NotFound_Msg msg, NotFound_Model model ) ->
|
||||||
|
pages.notFound.update msg model
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
-- msg doesn't match model, no update
|
||||||
|
( model_, Cmd.none, Cmd.none )
|
||||||
|
```
|
||||||
|
|
||||||
|
### view + subscriptions
|
||||||
|
|
||||||
|
```elm
|
||||||
|
bundle Model -> Global.Model -> ( Model, Cmd Msg, Cmd Global.Msg )
|
||||||
|
bundle model_ =
|
||||||
|
case model_ of
|
||||||
|
Top_Model model ->
|
||||||
|
pages.top.bundle model
|
||||||
|
|
||||||
|
AboutUs_Model model ->
|
||||||
|
pages.aboutUs.bundle model
|
||||||
|
|
||||||
|
Posts_Model model ->
|
||||||
|
pages.posts.bundle model
|
||||||
|
|
||||||
|
Post_Model model ->
|
||||||
|
pages.post.bundle model
|
||||||
|
|
||||||
|
NotFound_Model model ->
|
||||||
|
pages.notFound.bundle model
|
||||||
|
|
||||||
|
|
||||||
|
view : Model -> Global.Model -> Document Msg
|
||||||
|
view model =
|
||||||
|
bundle model >> .view
|
||||||
|
|
||||||
|
|
||||||
|
subscriptions : Model -> Global.Model -> Sub Msg
|
||||||
|
subscriptions model =
|
||||||
|
bundle model >> .subscriptions
|
||||||
|
```
|
||||||
|
|
||||||
|
Each function provides page-specific flags, model, or msg values and returns the same `Model` and `Msg` types that the functions expect.
|
||||||
|
|
||||||
|
No need to manually upgrade these by hand.
|
||||||
|
|
||||||
|
|
||||||
|
## src/Page.elm
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
|
||||||
|
## src/Page/Top.elm
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
|
||||||
|
## src/Page/AboutUs.elm
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
|
||||||
|
## src/Page/Posts.elm
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
|
||||||
|
## src/Page/Post.elm
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
|
||||||
|
## src/Page/NotFoun.elm
|
||||||
|
|
||||||
|
TODO
|
||||||
|
Loading…
Reference in New Issue
Block a user