├── .gitignore ├── elm-package.json ├── README.md └── main.elm /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | elm-stuff 3 | -------------------------------------------------------------------------------- /elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "helpful summary of your project, less than 80 characters", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | "." 8 | ], 9 | "exposed-modules": [], 10 | "dependencies": { 11 | "elm-lang/core": "5.0.0 <= v < 6.0.0", 12 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 13 | "elm-lang/navigation": "2.0.0 <= v < 3.0.0", 14 | "evancz/url-parser": "2.0.0 <= v < 3.0.0" 15 | }, 16 | "elm-version": "0.18.0 <= v < 0.19.0" 17 | } 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Elm SPA example 2 | 3 | ## Install 4 | 5 | - npm install 6 | - elm-package install 7 | 8 | Run with elm-reactor and go to `http://localhost:8000` 9 | 10 | ## Processs 11 | 12 | - [X] **Step 0**: Create a basic app - https://github.com/AdrianRibao/elm-spa-example/tree/step0 13 | - [X] **Step 1**: Create basic navigation - https://github.com/AdrianRibao/elm-spa-example/tree/step1 14 | - [X] **Step 2**: Navigation with URL changes - https://github.com/AdrianRibao/elm-spa-example/tree/step2 15 | - [X] **Step 3**: Cleaning up and use UrlParser - https://github.com/AdrianRibao/elm-spa-example/tree/step3 16 | - [X] **Step 4**: Add a new page with parameters - https://github.com/AdrianRibao/elm-spa-example/tree/step4 17 | -------------------------------------------------------------------------------- /main.elm: -------------------------------------------------------------------------------- 1 | module SPA exposing (..) 2 | 3 | import Html exposing (..) 4 | import Html.Events exposing (onClick) 5 | import Navigation exposing (..) 6 | import UrlParser exposing (..) 7 | 8 | 9 | main = 10 | Navigation.program locFor 11 | { init = init 12 | , update = update 13 | , view = view 14 | , subscriptions = subscriptions 15 | } 16 | 17 | 18 | 19 | -- ROUTING 20 | 21 | 22 | route : Parser (Page -> a) a 23 | route = 24 | oneOf 25 | [ UrlParser.map Home (UrlParser.s "home") 26 | , UrlParser.map Login (UrlParser.s "login") 27 | , UrlParser.map About (UrlParser.s "about") 28 | , UrlParser.map PostShow (UrlParser.s "post" int) 29 | ] 30 | 31 | 32 | locFor : Location -> Msg 33 | locFor location = 34 | parseHash route location 35 | |> GoTo 36 | 37 | 38 | 39 | -- MODEL 40 | 41 | 42 | type Page 43 | = Home 44 | | Login 45 | | About 46 | | PostShow Int 47 | 48 | 49 | type alias Model = 50 | { currentPage : Page 51 | } 52 | 53 | 54 | init : Location -> ( Model, Cmd Msg ) 55 | init location = 56 | let 57 | page = 58 | case parseHash route location of 59 | Nothing -> 60 | Home 61 | 62 | Just page -> 63 | page 64 | in 65 | ( Model page, Cmd.none ) 66 | 67 | 68 | 69 | -- UPDATE 70 | 71 | 72 | type Msg 73 | = GoTo (Maybe Page) 74 | | LinkTo String 75 | 76 | 77 | update : Msg -> Model -> ( Model, Cmd Msg ) 78 | update msg model = 79 | case msg of 80 | GoTo maybepage -> 81 | case maybepage of 82 | Nothing -> 83 | ( { model | currentPage = Home }, Cmd.none ) 84 | 85 | Just page -> 86 | ( { model | currentPage = page }, Cmd.none ) 87 | 88 | LinkTo path -> 89 | ( model, newUrl path ) 90 | 91 | 92 | 93 | -- VIEW 94 | 95 | 96 | view : Model -> Html Msg 97 | view model = 98 | div [] 99 | [ h1 [] [ text "SPA application" ] 100 | , render_menu model 101 | , render_page model 102 | ] 103 | 104 | 105 | render_menu : Model -> Html Msg 106 | render_menu model = 107 | div [] 108 | [ button [ onClick (LinkTo "#home") ] [ text "Home" ] 109 | , button [ onClick (LinkTo "#login") ] [ text "Login" ] 110 | , button [ onClick (LinkTo "#about") ] [ text "About" ] 111 | , button [ onClick (LinkTo "#post/17") ] [ text "Go to post 17" ] 112 | ] 113 | 114 | 115 | render_page : Model -> Html Msg 116 | render_page model = 117 | let 118 | page_content = 119 | case model.currentPage of 120 | Home -> 121 | text "Home" 122 | 123 | Login -> 124 | text "Login" 125 | 126 | About -> 127 | text "About" 128 | 129 | PostShow postid -> 130 | text ("Render the post with id: " ++ toString postid) 131 | in 132 | div [] [ page_content ] 133 | 134 | 135 | 136 | -- SUBSCRIPTIONS 137 | 138 | 139 | subscriptions : Model -> Sub Msg 140 | subscriptions model = 141 | Sub.none 142 | --------------------------------------------------------------------------------