Created
January 24, 2017 03:18
-
-
Save mdemin914/0baf793dce856ffe57ce31979ad600d6 to your computer and use it in GitHub Desktop.
Composing pages with a nav
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main exposing (..) | |
import Html exposing (..) | |
import Html.Events exposing (onInput, onClick) | |
-- MODELS | |
type alias Model = | |
{ page : Page | |
, page1model : Page1Model | |
, page2model : Page2Model | |
} | |
model : Model | |
model = | |
Model Page1 emptyPage1 emptyPage2 | |
type alias Page1Model = | |
{ field1 : String | |
, field2 : String | |
} | |
emptyPage1 : Page1Model | |
emptyPage1 = | |
{ field1 = "" | |
, field2 = "" | |
} | |
type alias Page2Model = | |
{ field1 : String | |
, field2 : String | |
} | |
emptyPage2 : Page2Model | |
emptyPage2 = | |
{ field1 = "" | |
, field2 = "" | |
} | |
type Page | |
= Page1 | |
| Page2 | |
type Msg | |
= Msg1 Page1Msg | |
| Msg2 Page2Msg | |
| Navigate String | |
| Logout | |
type Page1Msg | |
= DoSomething1 | |
| Navigate1 String | |
| Logout1 | |
type Page2Msg | |
= DoSomething2 | |
| Navigate2 String | |
| Logout2 | |
-- UPDATE | |
page1update : Page1Msg -> Page1Model -> ( Page1Model, Cmd Msg ) | |
page1update msg model = | |
case msg of | |
DoSomething1 -> | |
( { model | field1 = "1" }, Cmd.none ) | |
Navigate1 url -> | |
( model, navigate url ) | |
Logout1 -> | |
( model, logout ) | |
page2update : Page2Msg -> Page2Model -> ( Page2Model, Cmd Msg ) | |
page2update msg model = | |
case msg of | |
DoSomething2 -> | |
( { model | field2 = "2" }, Cmd.none ) | |
Navigate2 url -> | |
( model, navigate url ) | |
Logout2 -> | |
( model, logout ) | |
update : Msg -> Model -> ( Model, Cmd Msg ) | |
update msg model = | |
case msg of | |
Msg1 msg1 -> | |
let | |
( newModel, cmd ) = | |
page1update msg1 model.page1model | |
in | |
( { model | page1model = newModel }, cmd ) | |
Msg2 msg2 -> | |
let | |
( newModel, cmd ) = | |
page2update msg2 model.page2model | |
in | |
( { model | page2model = newModel }, cmd ) | |
Navigate url -> | |
( model, navigate url ) | |
Logout -> | |
( model, logout ) | |
-- VIEW | |
-- super complex page which does a bunch of stuff not related to page2 | |
-- option 1: change the the functions to all return Html Msg and | |
-- map everything in the page | |
-- pros: dont need to add a logout / navigate msg for each page | |
-- cons: a lot of Html.maps? | |
page1view_ : Page1Model -> Html Msg | |
page1view_ model = | |
div [] | |
[ nav | |
, Html.map Msg1 (div [ onClick DoSomething1 ] [ text model.field1 ]) | |
, Html.map Msg1 (div [ onClick DoSomething1 ] [ text model.field2 ]) | |
] | |
-- super complex page which does a bunch of stuff | |
-- option 2: implement Navigate and Logout as a Page1Msg / Page2Msg for each page | |
-- and implement nav to accept msg instead of Msg | |
-- pros: dont need to Html.Map everything | |
-- cons: duplication of Navigate/Logout methods for each page | |
page1view__ : Page1Model -> Html Page1Msg | |
page1view__ model = | |
div [] | |
[ nav_ Navigate1 Logout1 | |
, div [ onClick DoSomething1 ] [ text model.field1 ] | |
, div [ onClick DoSomething1 ] [ text model.field2 ] | |
] | |
-- option 3: ??????? | |
-- what is the best practice here to have a nav that can be used across pages | |
option3 : Html msg | |
option3 = | |
div [] [] | |
--nav stuff | |
nav : Html Msg | |
nav = | |
div [] | |
[ a [ onClick (Navigate "Page1") ] [ text "Page 1" ] | |
, a [ onClick (Navigate "Page2") ] [ text "Page 2" ] | |
, a [ onClick Logout ] [ text "Logout" ] | |
] | |
nav_ : (String -> msg) -> msg -> Html msg | |
nav_ navigate logout = | |
div [] | |
[ a [ onClick (navigate "Page1") ] [ text "Page 1" ] | |
, a [ onClick (navigate "Page2") ] [ text "Page 2" ] | |
, a [ onClick logout ] [ text "Logout" ] | |
] | |
-- super complex page with a bunch of stuff | |
-- and it also has a nav bar, the messages are duplicated | |
page2view : Page2Model -> Html Page2Msg | |
page2view model = | |
div [ onClick DoSomething2 ] | |
[ nav_ Navigate2 Logout2 | |
, text model.field2 | |
] | |
-- main function that shows everything when needed | |
view : Model -> Html Msg | |
view model = | |
div [] | |
[ page1view_ model.page1model | |
, Html.map Msg2 (page2view model.page2model) | |
] | |
-- Commands | |
logout : Cmd msg | |
logout = | |
Cmd.none | |
navigate : String -> Cmd msg | |
navigate url = | |
Cmd.none | |
-- | |
init : ( Model, Cmd Msg ) | |
init = | |
( model | |
, Cmd.none | |
) | |
main : Program Never Model Msg | |
main = | |
Html.program | |
{ init = init | |
, update = update | |
, subscriptions = \_ -> Sub.none | |
, view = view | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here is another approach: