├── .editorconfig ├── .gitignore ├── .vscode └── settings.json ├── LANGS.md ├── Makefile ├── README.md ├── book.json ├── elm-package.json ├── elm.png ├── en-v01 ├── 01-foundations │ ├── 01-hello.elm │ ├── 01-hello.md │ ├── 02-functions.md │ ├── 03-functions-2.md │ ├── 04-imports-and-modules.md │ ├── 05-union-types.md │ ├── 06-type-aliases.md │ ├── 07-unit-type.md │ └── cover.md ├── 02-elm-arch │ ├── 01-introduction.elm │ ├── 01-introduction.md │ ├── 02-structure.md │ ├── 03-messages.elm │ ├── 03-messages.md │ ├── 04-flow.md │ ├── 04-flow.png │ ├── 04-flow.pu │ ├── 05-msg-payload.elm │ ├── 05-msg-payload.md │ ├── 06-composing.md │ ├── 06-composing.png │ ├── 06-composing.pu │ ├── 06-composing │ │ ├── Main.elm │ │ ├── Widget.elm │ │ └── elm-package.json │ ├── 06-composing_001.png │ ├── 07-composing-2.md │ ├── 08-composing-3.md │ └── cover.md ├── 03-subs-cmds │ ├── 01-subs.elm │ ├── 01-subs.md │ ├── 02-commands.elm │ ├── 02-commands.md │ ├── 02-commands.png │ ├── 02-commands.pu │ └── cover.md ├── 04-starting │ ├── 01-planning.md │ ├── 01-planning.odg │ ├── 01-planning.png │ ├── 02-backend.md │ ├── 03-webpack-1.md │ ├── 04-webpack-2.md │ ├── 05-webpack-3.md │ ├── 06-webpack-4.md │ ├── 07-multiple-modules.md │ └── cover.md ├── 05-resources │ ├── 01-intro.md │ ├── 02-players.md │ ├── 03-players-list.md │ ├── 04-main-mods.md │ ├── 05-main-view.md │ ├── 06-main.md │ ├── cover.md │ └── screenshot.png ├── 06-fetching-resources │ ├── 01-plan.md │ ├── 01-plan.png │ ├── 01-plan.pu │ ├── 02-players-messages.md │ ├── 03-players-update.md │ ├── 04-players-cmds.md │ ├── 05-main.md │ ├── 06-try-it.md │ ├── cover.md │ └── screenshot.png ├── 07-routing │ ├── 01-intro.md │ ├── 01-intro.png │ ├── 01-intro.pu │ ├── 01-intro_001.png │ ├── 02-routing.md │ ├── 03-player-edit.md │ ├── 04-main-model.md │ ├── 05-main-messages.md │ ├── 06-main-update.md │ ├── 07-main-view.md │ ├── 08-main.md │ ├── 09-edit.png │ ├── 09-list.png │ ├── 09-try-it.md │ ├── 10-navigation.md │ └── cover.md ├── 08-edit │ ├── 01-plan.md │ ├── 01-plan.png │ ├── 01-plan.pu │ ├── 02-messages.md │ ├── 03-player-edit.md │ ├── 04-commands.md │ ├── 05-update.md │ └── cover.md ├── 09-conclusion │ ├── 01-improvements.md │ └── cover.md ├── README.md ├── SUMMARY.md ├── logo.png └── tips-tricks │ ├── context.md │ ├── point-free-style.md │ └── troubleshooting.md ├── en-v03 ├── 01-intro │ ├── 01-requirements.md │ ├── 02-foundations.md │ ├── 03-plan.md │ └── 03-plan.png ├── 02-start │ ├── 01-project.md │ └── 02-backend.md ├── README.md └── SUMMARY.md ├── en ├── 01-foundations │ ├── 01-hello.elm │ ├── 01-hello.md │ ├── 02-functions.md │ ├── 03-functions-2.md │ ├── 04-imports-and-modules.md │ ├── 05-union-types.md │ ├── 06-type-aliases.md │ ├── 07-unit-type.md │ └── cover.md ├── 02-elm-arch │ ├── 01-introduction.elm │ ├── 01-introduction.md │ ├── 02-structure.md │ ├── 03-messages.elm │ ├── 03-messages.md │ ├── 04-flow.md │ ├── 04-flow.png │ ├── 04-flow.pu │ ├── 05-msg-payload.elm │ ├── 05-msg-payload.md │ └── cover.md ├── 03-subs-cmds │ ├── 01-subs.elm │ ├── 01-subs.md │ ├── 02-commands.elm │ ├── 02-commands.md │ ├── 02-commands.png │ ├── 02-commands.pu │ └── cover.md ├── 04-starting │ ├── 01-planning.md │ ├── 01-planning.odg │ ├── 01-planning.png │ ├── 02-backend.md │ ├── 03-webpack-1.md │ ├── 04-webpack-2.md │ ├── 05-webpack-3.md │ ├── 06-webpack-4.md │ ├── 07-multiple-modules.md │ └── cover.md ├── 05-resources │ ├── 01-intro.md │ ├── 02-models.md │ ├── 03-main.md │ ├── 04-players-list.md │ ├── 05-main-view.md │ ├── cover.md │ └── screenshot.png ├── 06-fetching-resources │ ├── 01-plan.md │ ├── 01-plan.png │ ├── 01-plan.pu │ ├── 02-messages.md │ ├── 03-models.md │ ├── 04-commands.md │ ├── 05-update.md │ ├── 06-views.md │ ├── 07-try-it.md │ ├── checklist.md │ ├── cover.md │ └── screenshot.png ├── 07-routing │ ├── 01-intro.md │ ├── 01-intro.png │ ├── 01-intro.pu │ ├── 01-intro_001.png │ ├── 02-routing.md │ ├── 03-player-edit.md │ ├── 04-models.md │ ├── 05-messages.md │ ├── 06-update.md │ ├── 07-view.md │ ├── 08-main.md │ ├── 09-edit.png │ ├── 09-list.png │ ├── 09-try-it.md │ ├── 10-navigation.md │ ├── 11-try-it.md │ ├── checklist.md │ └── cover.md ├── 08-edit │ ├── 01-plan.md │ ├── 01-plan.png │ ├── 01-plan.pu │ ├── 02-messages.md │ ├── 03-player-edit.md │ ├── 04-commands.md │ ├── 05-update.md │ ├── checklist.md │ └── cover.md ├── 09-conclusion │ ├── 01-improvements.md │ └── cover.md ├── README.md ├── SUMMARY.md ├── logo.png └── tips-tricks │ ├── context.md │ ├── point-free-style.md │ └── troubleshooting.md ├── es ├── 01-fundamentos │ ├── 01-hola-mundo.md │ ├── 02-funciones.md │ ├── 03-functiones-2.md │ ├── 04-imports-y-modules.md │ ├── 05-tipos-union.md │ ├── 06-tipos-aliases.md │ ├── 07-tipos-unit.md │ └── cover.md ├── 02-elm-arch │ └── cover.md ├── README.md ├── SUMMARY.md └── logo.png ├── fr ├── 01-fondations │ ├── 01-hello.elm │ ├── 01-hello.md │ ├── 02-fonctions.md │ ├── 03-fonctions-2.md │ ├── 04-imports-et-modules.md │ ├── 05-types-d-union.md │ ├── 06-alias-de-type.md │ ├── 07-le-type-unit.md │ └── couverture.md ├── 02-elm-arch │ ├── 01-introduction.elm │ ├── 01-introduction.md │ ├── 02-structure.md │ ├── 03-messages.elm │ ├── 03-messages.md │ ├── 04-flux.md │ ├── 04-flux.png │ ├── 04-flux.pu │ ├── 05-messages-et-donnees-attachees.elm │ ├── 05-messages-et-donnees-attachees.md │ ├── 06-composition.md │ ├── 06-composition.png │ ├── 06-composition.pu │ ├── 06-composition │ │ ├── Main.elm │ │ ├── Widget.elm │ │ └── elm-package.json │ ├── 06-composition_001.png │ ├── 07-composition-2.md │ ├── 08-composition-3.md │ └── cover.md ├── 03-subs-cmds │ ├── 01-souscriptions.elm │ ├── 01-souscriptions.md │ ├── 02-commandes.elm │ ├── 02-commandes.md │ ├── 02-commandes.png │ ├── 02-commandes.pu │ └── cover.md ├── 04-commencer │ ├── 01-preparation.md │ ├── 01-preparation.odg │ ├── 01-preparation.png │ ├── 02-serveur-de-donnees.md │ ├── 03-webpack-1.md │ ├── 03-webpack.md │ ├── 04-webpack-2.md │ ├── 05-webpack-3.md │ ├── 06-webpack-4.md │ ├── 07-plusieurs-modules.md │ └── cover.md ├── 05-ressources │ ├── 01-intro.md │ ├── 02-joueurs.md │ ├── 03-liste-joueurs.md │ ├── 04-modules-principaux.md │ ├── 05-vue-principale.md │ ├── 06-main.md │ ├── capture.png │ └── cover.md ├── 06-recuperation-ressources │ ├── 01-plan.md │ ├── 01-plan.png │ ├── 01-plan.pu │ ├── 02-messages-joueurs.md │ ├── 03-mise-a-jour-joueurs.md │ ├── 04-commandes-joueurs.md │ ├── 05-main.md │ ├── 06-essayez.md │ ├── capture.png │ └── cover.md ├── 07-routage │ ├── 01-intro.md │ ├── 01-intro.png │ ├── 01-intro.pu │ ├── 01-intro_001.png │ ├── 02-routage.md │ ├── 03-edition-joueur.md │ ├── 04-modele-main.md │ ├── 05-main-messages.md │ ├── 06-main-update.md │ ├── 07-vue-main.md │ ├── 08-main.md │ ├── 09-edition.png │ ├── 09-essayez.md │ ├── 09-liste.png │ ├── 10-navigation.md │ └── cover.md ├── 08-edition │ ├── 01-plan.md │ ├── 01-plan.png │ ├── 01-plan.pu │ ├── 02-messages.md │ ├── 03-edition-du-joueur.md │ ├── 04-commandes.md │ ├── 05-mise-a-jour.md │ └── cover.md ├── 09-conclusion │ ├── 01-ameliorations.md │ └── cover.md ├── README.md ├── SUMMARY.md ├── logo.png └── tips-tricks │ ├── context.md │ ├── point-free-style.md │ └── troubleshooting.md ├── helpers.md ├── jp ├── 01-foundations │ ├── 01-hello.elm │ ├── 01-hello.md │ ├── 02-functions.md │ ├── 03-functions-2.md │ ├── 04-imports-and-modules.md │ ├── 05-union-types.md │ ├── 06-type-aliases.md │ ├── 07-unit-type.md │ └── cover.md ├── 02-elm-arch │ ├── 01-introduction.elm │ ├── 01-introduction.md │ ├── 02-structure.md │ ├── 03-messages.elm │ ├── 03-messages.md │ ├── 04-flow.md │ ├── 04-flow.png │ ├── 04-flow.pu │ ├── 05-msg-payload.elm │ ├── 05-msg-payload.md │ ├── 06-composing.md │ ├── 06-composing.png │ ├── 06-composing.pu │ ├── 06-composing │ │ ├── Main.elm │ │ ├── Widget.elm │ │ └── elm-package.json │ ├── 06-composing_001.png │ ├── 07-composing-2.md │ ├── 08-composing-3.md │ └── cover.md ├── 03-subs-cmds │ ├── 01-subs.elm │ ├── 01-subs.md │ ├── 02-commands.elm │ ├── 02-commands.md │ ├── 02-commands.png │ ├── 02-commands.pu │ └── cover.md ├── 04-starting │ ├── 01-planning.md │ ├── 01-planning.odg │ ├── 01-planning.png │ ├── 02-backend.md │ ├── 03-webpack-1.md │ ├── 04-webpack-2.md │ ├── 05-webpack-3.md │ ├── 06-webpack-4.md │ ├── 07-multiple-modules.md │ └── cover.md ├── 05-resources │ ├── 01-intro.md │ ├── 02-players.md │ ├── 03-players-list.md │ ├── 04-main-mods.md │ ├── 05-main-view.md │ ├── 06-main.md │ ├── cover.md │ └── screenshot.png ├── 06-fetching-resources │ ├── 01-plan.md │ ├── 01-plan.png │ ├── 01-plan.pu │ ├── 02-players-messages.md │ ├── 03-players-update.md │ ├── 04-players-cmds.md │ ├── 05-main.md │ ├── 06-try-it.md │ ├── cover.md │ └── screenshot.png ├── 07-routing │ ├── 01-intro.md │ ├── 01-intro.png │ ├── 01-intro.pu │ ├── 01-intro_001.png │ ├── 02-routing.md │ ├── 03-player-edit.md │ ├── 04-main-model.md │ ├── 05-main-messages.md │ ├── 06-main-update.md │ ├── 07-main-view.md │ ├── 08-main.md │ ├── 09-edit.png │ ├── 09-list.png │ ├── 09-try-it.md │ ├── 10-navigation.md │ └── cover.md ├── 08-edit │ ├── 01-plan.md │ ├── 01-plan.png │ ├── 01-plan.pu │ ├── 02-messages.md │ ├── 03-player-edit.md │ ├── 04-commands.md │ ├── 05-update.md │ └── cover.md ├── 09-conclusion │ ├── 01-improvements.md │ └── cover.md ├── README.md ├── SUMMARY.md ├── logo.png └── tips-tricks │ ├── context.md │ ├── point-free-style.md │ └── troubleshooting.md ├── ko ├── 01-foundations │ ├── 01-hello.elm │ ├── 01-hello.md │ ├── 02-functions.md │ ├── 03-functions-2.md │ ├── 04-imports-and-modules.md │ ├── 05-union-types.md │ ├── 06-type-aliases.md │ ├── 07-unit-type.md │ └── cover.md ├── 02-elm-arch │ ├── 01-introduction.elm │ ├── 01-introduction.md │ ├── 02-structure.md │ ├── 03-messages.elm │ ├── 03-messages.md │ ├── 04-flow.md │ ├── 04-flow.png │ ├── 04-flow.pu │ ├── 05-msg-payload.elm │ ├── 05-msg-payload.md │ ├── 06-composing.md │ ├── 06-composing.png │ ├── 06-composing.pu │ ├── 06-composing │ │ ├── Main.elm │ │ ├── Widget.elm │ │ └── elm-package.json │ ├── 06-composing_001.png │ ├── 07-composing-2.md │ ├── 08-composing-3.md │ └── cover.md ├── 03-subs-cmds │ ├── 01-subs.elm │ ├── 01-subs.md │ ├── 02-commands.elm │ ├── 02-commands.md │ ├── 02-commands.png │ ├── 02-commands.pu │ └── cover.md ├── 04-starting │ ├── 01-planning.md │ ├── 01-planning.odg │ ├── 01-planning.png │ ├── 02-backend.md │ ├── 03-webpack-1.md │ ├── 04-webpack-2.md │ ├── 05-webpack-3.md │ ├── 06-webpack-4.md │ ├── 07-multiple-modules.md │ └── cover.md ├── 05-resources │ ├── 01-intro.md │ ├── 02-players.md │ ├── 03-players-list.md │ ├── 04-main-mods.md │ ├── 05-main-view.md │ ├── 06-main.md │ ├── cover.md │ └── screenshot.png ├── 06-fetching-resources │ ├── 01-plan.md │ ├── 01-plan.png │ ├── 01-plan.pu │ ├── 02-players-messages.md │ ├── 03-players-update.md │ ├── 04-players-cmds.md │ ├── 05-main.md │ ├── 06-try-it.md │ ├── cover.md │ └── screenshot.png ├── 07-routing │ ├── 01-intro.md │ ├── 01-intro.png │ ├── 01-intro.pu │ ├── 01-intro_001.png │ ├── 02-routing.md │ ├── 03-player-edit.md │ ├── 04-main-model.md │ ├── 05-main-messages.md │ ├── 06-main-update.md │ ├── 07-main-view.md │ ├── 08-main.md │ ├── 09-edit.png │ ├── 09-list.png │ ├── 09-try-it.md │ ├── 10-navigation.md │ └── cover.md ├── 08-edit │ ├── 01-plan.md │ ├── 01-plan.png │ ├── 01-plan.pu │ ├── 02-messages.md │ ├── 03-player-edit.md │ ├── 04-commands.md │ ├── 05-update.md │ └── cover.md ├── 09-conclusion │ ├── 01-improvements.md │ └── cover.md ├── README.md ├── SUMMARY.md ├── logo.png └── tips-tricks │ ├── context.md │ ├── point-free-style.md │ └── troubleshooting.md └── zh-TW ├── 01-foundations ├── 01-hello.elm ├── 01-hello.md ├── 02-functions.md ├── 03-functions-2.md ├── 04-imports-and-modules.md ├── 05-union-types.md ├── 06-type-aliases.md ├── 07-unit-type.md └── cover.md ├── 02-elm-arch ├── 01-introduction.elm ├── 01-introduction.md ├── 02-structure.md ├── 03-messages.elm ├── 03-messages.md ├── 04-flow.md ├── 04-flow.png ├── 04-flow.pu ├── 05-msg-payload.elm ├── 05-msg-payload.md ├── 06-composing.md ├── 06-composing.png ├── 06-composing.pu ├── 06-composing │ ├── Main.elm │ ├── Widget.elm │ └── elm-package.json ├── 06-composing_001.png ├── 07-composing-2.md ├── 08-composing-3.md └── cover.md ├── 03-subs-cmds ├── 01-subs.elm ├── 01-subs.md ├── 02-commands.elm ├── 02-commands.md ├── 02-commands.png ├── 02-commands.pu └── cover.md ├── 04-starting ├── 01-planning.md ├── 01-planning.odg ├── 01-planning.png ├── 02-backend.md ├── 03-webpack-1.md ├── 04-webpack-2.md ├── 05-webpack-3.md ├── 06-webpack-4.md ├── 07-multiple-modules.md └── cover.md ├── 05-resources ├── 01-intro.md ├── 02-players.md ├── 03-players-list.md ├── 04-main-mods.md ├── 05-main-view.md ├── 06-main.md ├── cover.md └── screenshot.png ├── 06-fetching-resources ├── 01-plan.md ├── 01-plan.png ├── 01-plan.pu ├── 02-players-messages.md ├── 03-players-update.md ├── 04-players-cmds.md ├── 05-main.md ├── 06-try-it.md ├── cover.md └── screenshot.png ├── 07-routing ├── 01-intro.md ├── 01-intro.png ├── 01-intro.pu ├── 01-intro_001.png ├── 02-routing.md ├── 03-player-edit.md ├── 04-main-model.md ├── 05-main-messages.md ├── 06-main-update.md ├── 07-main-view.md ├── 08-main.md ├── 09-edit.png ├── 09-list.png ├── 09-try-it.md ├── 10-navigation.md └── cover.md ├── 08-edit ├── 01-plan.md ├── 01-plan.png ├── 01-plan.pu ├── 02-messages.md ├── 03-player-edit.md ├── 04-commands.md ├── 05-update.md └── cover.md ├── 09-conclusion ├── 01-improvements.md └── cover.md ├── GLOSSARY.md ├── README.md ├── SUMMARY.md ├── logo.png └── tips-tricks ├── context.md ├── point-free-style.md └── troubleshooting.md /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | 8 | [*.yml] 9 | indent_style = space 10 | indent_size = 2 11 | 12 | [Makefile] 13 | indent_style = tab 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | elm-stuff 3 | code/elm.js 4 | code/node_modules 5 | 6 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "search.exclude": { 4 | "**/node_modules": true, 5 | "**/bower_components": true, 6 | "**/elm-stuff": true 7 | } 8 | } -------------------------------------------------------------------------------- /LANGS.md: -------------------------------------------------------------------------------- 1 | # Languages 2 | 3 | * [English - WIP - Elm 0.19](en-v03/) 4 | * [English - v2 - Elm 0.18](en/) 5 | * [English - v1 - Elm 0.18](en-v01/) 6 | * [Français - v1 - Elm 0.18](fr/) 7 | * [日本語 - v1 - Elm 0.18](jp/) 8 | * [中文(繁體) - v1 - Elm 0.18](zh-TW/) 9 | * [한국어 - v1 - Elm 0.18](ko/) 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | pu-elm-arch-flow: 2 | plantuml en/02-elm-arch/04-flow.pu 3 | plantuml fr/02-elm-arch/04-flux.pu 4 | plantuml jp/02-elm-arch/04-flux.pu 5 | 6 | pu-comp: 7 | plantuml en/02-elm-arch/06-composing.pu 8 | plantuml jp/02-elm-arch/06-composing.pu 9 | 10 | pu-comd: 11 | plantuml en/03-subs-cmds/02-commands.pu 12 | plantuml fr/03-subs-cmds/02-commandes.pu 13 | plantuml jp/03-subs-cmds/02-commands.pu 14 | 15 | pu-fetch: 16 | plantuml en/06-fetching-resources/01-plan.pu 17 | plantuml fr/06-recuperation-ressources/01-plan.pu 18 | plantuml jp/06-fetching-resources/01-plan.pu 19 | 20 | pu-routing: 21 | plantuml en/07-routing/01-intro.pu 22 | plantuml jp/07-routing/01-intro.pu 23 | 24 | pu-edit: 25 | plantuml en/08-edit/01-plan.pu 26 | plantuml jp/08-edit/01-plan.pu 27 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /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/http": "1.0.0 <= v < 2.0.0", 14 | "elm-lang/keyboard": "1.0.1 <= v < 2.0.0", 15 | "elm-lang/mouse": "1.0.1 <= v < 2.0.0" 16 | }, 17 | "elm-version": "0.18.0 <= v < 0.19.0" 18 | } 19 | -------------------------------------------------------------------------------- /elm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/elm.png -------------------------------------------------------------------------------- /en-v01/01-foundations/01-hello.elm: -------------------------------------------------------------------------------- 1 | module Hello exposing (..) 2 | 3 | import Html exposing (text) 4 | 5 | 6 | main = 7 | text "Hello" 8 | -------------------------------------------------------------------------------- /en-v01/01-foundations/cover.md: -------------------------------------------------------------------------------- 1 | # Foundations 2 | 3 | This chapter covers: 4 | 5 | - Running a basic Elm application 6 | - Basic of functions and types in Elm -------------------------------------------------------------------------------- /en-v01/02-elm-arch/01-introduction.elm: -------------------------------------------------------------------------------- 1 | module App exposing (..) 2 | 3 | import Html exposing (Html, div, text, program) 4 | 5 | 6 | -- MODEL 7 | 8 | 9 | type alias Model = 10 | String 11 | 12 | 13 | init : ( Model, Cmd Msg ) 14 | init = 15 | ( "Hello", Cmd.none ) 16 | 17 | 18 | 19 | -- MESSAGES 20 | 21 | 22 | type Msg 23 | = NoOp 24 | 25 | 26 | 27 | -- VIEW 28 | 29 | 30 | view : Model -> Html Msg 31 | view model = 32 | div [] 33 | [ text model ] 34 | 35 | 36 | 37 | -- UPDATE 38 | 39 | 40 | update : Msg -> Model -> ( Model, Cmd Msg ) 41 | update msg model = 42 | case msg of 43 | NoOp -> 44 | ( model, Cmd.none ) 45 | 46 | 47 | 48 | -- SUBSCRIPTIONS 49 | 50 | 51 | subscriptions : Model -> Sub Msg 52 | subscriptions model = 53 | Sub.none 54 | 55 | 56 | 57 | -- MAIN 58 | 59 | 60 | main : Program Never Model Msg 61 | main = 62 | program 63 | { init = init 64 | , view = view 65 | , update = update 66 | , subscriptions = subscriptions 67 | } 68 | -------------------------------------------------------------------------------- /en-v01/02-elm-arch/04-flow.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Application flow 4 | 5 | The following diagram illustrates how the pieces of our application interact with Html.program. 6 | 7 | ![Flow](04-flow.png) 8 | 9 | 1. `Html.program` calls our view function with the initial model and renders it. 10 | 1. When the user clicks on the Expand button, the view triggers the `Expand` message. 11 | 1. `Html.program` receives the `Expand` message which calls our `update` function with `Expand` and the current application state. 12 | 1. The update function responds to the message by returning the updated state and a command to run (or `Cmd.none`). 13 | 1. `Html.program` receives the updated state, stores it, and calls the view with the updated state. 14 | 15 | Usually `Html.program` is the only place where an Elm application holds state, it is centralised in one big state tree. 16 | -------------------------------------------------------------------------------- /en-v01/02-elm-arch/04-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v01/02-elm-arch/04-flow.png -------------------------------------------------------------------------------- /en-v01/02-elm-arch/04-flow.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber 3 | participant program #white 4 | participant update #white 5 | participant view #white 6 | 7 | program -> view : Render view 8 | ||| 9 | view -> program : Trigger message e.g. Expand 10 | program -> update : Send message with the current state 11 | update --> program : Return updated state and command 12 | program -> view : Render view 13 | @enduml 14 | -------------------------------------------------------------------------------- /en-v01/02-elm-arch/05-msg-payload.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (Html, button, div, text, program) 4 | import Html.Events exposing (onClick) 5 | 6 | 7 | -- MODEL 8 | 9 | 10 | type alias Model = 11 | Int 12 | 13 | 14 | init : ( Model, Cmd Msg ) 15 | init = 16 | ( 0, Cmd.none ) 17 | 18 | 19 | 20 | -- MESSAGES 21 | 22 | 23 | type Msg 24 | = Increment Int 25 | 26 | 27 | 28 | -- VIEW 29 | 30 | 31 | view : Model -> Html Msg 32 | view model = 33 | div [] 34 | [ button [ onClick (Increment 2) ] [ text "+" ] 35 | , text (toString model) 36 | ] 37 | 38 | 39 | 40 | -- UPDATE 41 | 42 | 43 | update : Msg -> Model -> ( Model, Cmd Msg ) 44 | update msg model = 45 | case msg of 46 | Increment howMuch -> 47 | ( model + howMuch, Cmd.none ) 48 | 49 | 50 | 51 | -- SUBSCRIPTIONS 52 | 53 | 54 | subscriptions : Model -> Sub Msg 55 | subscriptions model = 56 | Sub.none 57 | 58 | 59 | 60 | -- MAIN 61 | 62 | 63 | main : Program Never Model Msg 64 | main = 65 | program 66 | { init = init 67 | , view = view 68 | , update = update 69 | , subscriptions = subscriptions 70 | } 71 | -------------------------------------------------------------------------------- /en-v01/02-elm-arch/06-composing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v01/02-elm-arch/06-composing.png -------------------------------------------------------------------------------- /en-v01/02-elm-arch/06-composing.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber "(#)" 3 | participant User #white 4 | participant program #white 5 | participant Main.initialModel as Mim #white 6 | participant Main.view as MV #white 7 | participant Main.update as MU #white 8 | participant Widget.initialModel as Wim #white 9 | participant Widget.view as WV #white 10 | participant Widget.update as WU #white 11 | 12 | program -> Mim: initialModel 13 | Mim -> Wim: initialModel 14 | Wim --> Mim: widgetModel 15 | Mim --> program: mainModel 16 | program -> MV : mainModel 17 | MV -> WV : widgetModel 18 | WV --> MV : Html 19 | MV --> program : Html 20 | program -> User : Html 21 | 22 | newpage 23 | 24 | autonumber 1 "(#)" 25 | User -> WV : Click 26 | WV -> MV: Increase 27 | MV -> program: (WidgetMsg Increase) 28 | program -> MU: (WidgetMsg Increase) mainModel 29 | MU -> WU : Increase widgetModel 30 | WU --> MU: (updated widgetModel, command) 31 | MU --> program: (updated mainModel, command) 32 | program -> MV : mainModel 33 | MV -> WV : widgetModel 34 | WV --> MV : Html 35 | MV --> program : Html 36 | @enduml 37 | -------------------------------------------------------------------------------- /en-v01/02-elm-arch/06-composing/Widget.elm: -------------------------------------------------------------------------------- 1 | module Widget exposing (..) 2 | 3 | import Html exposing (Html, button, div, text) 4 | import Html.Events exposing (onClick) 5 | 6 | 7 | -- MODEL 8 | 9 | 10 | type alias Model = 11 | { count : Int 12 | } 13 | 14 | 15 | initialModel : Model 16 | initialModel = 17 | { count = 0 18 | } 19 | 20 | 21 | type Msg 22 | = Increase 23 | 24 | 25 | 26 | -- VIEW 27 | 28 | 29 | view : Model -> Html Msg 30 | view model = 31 | div [] 32 | [ div [] [ text (toString model.count) ] 33 | , button [ onClick Increase ] [ Html.text "Click" ] 34 | ] 35 | 36 | 37 | 38 | -- UPDATE 39 | 40 | 41 | update : Msg -> Model -> ( Model, Cmd Msg ) 42 | update message model = 43 | case message of 44 | Increase -> 45 | ( { model | count = model.count + 1 }, Cmd.none ) 46 | -------------------------------------------------------------------------------- /en-v01/02-elm-arch/06-composing/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 | }, 14 | "elm-version": "0.18.0 <= v < 0.19.0" 15 | } -------------------------------------------------------------------------------- /en-v01/02-elm-arch/06-composing_001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v01/02-elm-arch/06-composing_001.png -------------------------------------------------------------------------------- /en-v01/02-elm-arch/cover.md: -------------------------------------------------------------------------------- 1 | # The Elm architecture 2 | 3 | This chapter covers: 4 | 5 | - Overview of the Elm architecture 6 | - Introduction to Html.program 7 | - Messages 8 | - Commands 9 | - Subscriptions -------------------------------------------------------------------------------- /en-v01/03-subs-cmds/02-commands.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (Html, div, button, text, program) 4 | import Html.Events exposing (onClick) 5 | import Random 6 | 7 | 8 | -- MODEL 9 | 10 | 11 | type alias Model = 12 | Int 13 | 14 | 15 | init : ( Model, Cmd Msg ) 16 | init = 17 | ( 1, Cmd.none ) 18 | 19 | 20 | 21 | -- MESSAGES 22 | 23 | 24 | type Msg 25 | = Roll 26 | | OnResult Int 27 | 28 | 29 | 30 | -- VIEW 31 | 32 | 33 | view : Model -> Html Msg 34 | view model = 35 | div [] 36 | [ button [ onClick Roll ] [ text "Roll" ] 37 | , text (toString model) 38 | ] 39 | 40 | 41 | 42 | -- UPDATE 43 | 44 | 45 | update : Msg -> Model -> ( Model, Cmd Msg ) 46 | update msg model = 47 | case msg of 48 | Roll -> 49 | ( model, Random.generate OnResult (Random.int 1 6) ) 50 | 51 | OnResult res -> 52 | ( res, Cmd.none ) 53 | 54 | 55 | 56 | -- MAIN 57 | 58 | 59 | main : Program Never Model Msg 60 | main = 61 | program 62 | { init = init 63 | , view = view 64 | , update = update 65 | , subscriptions = (always Sub.none) 66 | } 67 | -------------------------------------------------------------------------------- /en-v01/03-subs-cmds/02-commands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v01/03-subs-cmds/02-commands.png -------------------------------------------------------------------------------- /en-v01/03-subs-cmds/02-commands.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber "(#)" 3 | 4 | participant program #white 5 | participant Main.update as MU #white 6 | participant Child.update as CU #white 7 | participant GrandChild.update as GC #white 8 | 9 | program -> MU: update 10 | MU -> CU: update 11 | CU -> GC: update 12 | GC --> CU: (model, command) 13 | CU --> MU: (model, command) 14 | MU -> program : (model, command) 15 | 16 | @enduml 17 | -------------------------------------------------------------------------------- /en-v01/03-subs-cmds/cover.md: -------------------------------------------------------------------------------- 1 | # Subscriptions and Commands 2 | 3 | In order to listen to external input and create __side effects__ in our application we need to learn about __Subscriptions__ and __Commands__. 4 | 5 | This chapter covers: 6 | 7 | - Subscriptions 8 | - Commands 9 | -------------------------------------------------------------------------------- /en-v01/04-starting/01-planning.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Planning 4 | 5 | We will build a basic application to track an imaginary role playing game. 6 | 7 | ### Resources 8 | 9 | During the rest of this guide I will use the word __resources__ to refer to models that are the subject of our application. These are __players__ in this application. Using the word __model__ can be confusing because component specific state is also a model (for example the expanded / collapse state of a component). 10 | 11 | ## Wireframes 12 | 13 | The application will have two views: 14 | 15 | ![Plan](01-planning.png) 16 | 17 | ### Screen 1 18 | 19 | Will show a list of players. From here you can: 20 | 21 | - Navigate to edit a player 22 | 23 | ### Screen 2 24 | 25 | Shows the edit view for a player. In this screen you can: 26 | 27 | - Change the level 28 | 29 | This is a very simple application that will demonstrate: 30 | 31 | - Multiple views 32 | - Nested components 33 | - Breaking the application into resources 34 | - Routing 35 | - Shared state across the application 36 | - Read and edit operation on the records 37 | - Ajax requests -------------------------------------------------------------------------------- /en-v01/04-starting/01-planning.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v01/04-starting/01-planning.odg -------------------------------------------------------------------------------- /en-v01/04-starting/01-planning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v01/04-starting/01-planning.png -------------------------------------------------------------------------------- /en-v01/04-starting/05-webpack-3.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Webpack 3 4 | 5 | ## Initial Elm app 6 | 7 | Create a basic Elm app. In __src/Main.elm__: 8 | 9 | ```elm 10 | module Main exposing (..) 11 | 12 | import Html exposing (Html, div, text, program) 13 | 14 | 15 | -- MODEL 16 | 17 | 18 | type alias Model = 19 | String 20 | 21 | 22 | init : ( Model, Cmd Msg ) 23 | init = 24 | ( "Hello", Cmd.none ) 25 | 26 | 27 | 28 | -- MESSAGES 29 | 30 | 31 | type Msg 32 | = NoOp 33 | 34 | 35 | 36 | -- VIEW 37 | 38 | 39 | view : Model -> Html Msg 40 | view model = 41 | div [] 42 | [ text model ] 43 | 44 | 45 | 46 | -- UPDATE 47 | 48 | 49 | update : Msg -> Model -> ( Model, Cmd Msg ) 50 | update msg model = 51 | case msg of 52 | NoOp -> 53 | ( model, Cmd.none ) 54 | 55 | 56 | 57 | -- SUBSCRIPTIONS 58 | 59 | 60 | subscriptions : Model -> Sub Msg 61 | subscriptions model = 62 | Sub.none 63 | 64 | 65 | 66 | -- MAIN 67 | 68 | 69 | main : Program Never Model Msg 70 | main = 71 | program 72 | { init = init 73 | , view = view 74 | , update = update 75 | , subscriptions = subscriptions 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /en-v01/04-starting/cover.md: -------------------------------------------------------------------------------- 1 | # Starting an application 2 | 3 | In this chapter we start building an example Elm application. 4 | 5 | This tutorial will cover the following aspects about building an application: 6 | 7 | - Application structure 8 | - Fetching resources 9 | - Views 10 | - Routing 11 | - User interaction and saving changes 12 | 13 | See next page for details about the application. -------------------------------------------------------------------------------- /en-v01/05-resources/01-intro.md: -------------------------------------------------------------------------------- 1 | # The Players resource 2 | 3 | We will organise our application structure by the name of the resources in our application. In this app, we only have one resource (`Players`) so there will be only a `Players` directory. 4 | 5 | The `Players` directory will have modules just like the main level, one module per component of the Elm architecture: 6 | 7 | - Players/Messages.elm 8 | - Players/Models.elm 9 | - Players/Update.elm 10 | 11 | However, we will have different views for players: A list and a edit view. Each view will have its own Elm module: 12 | 13 | - Players/List.elm 14 | - Players/Edit.elm 15 | 16 | -------------------------------------------------------------------------------- /en-v01/05-resources/05-main-view.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Main View 4 | 5 | Modify __src/View.elm__ to include the list of players: 6 | 7 | ```elm 8 | module View exposing (..) 9 | 10 | import Html exposing (Html, div, text) 11 | import Messages exposing (Msg(..)) 12 | import Models exposing (Model) 13 | import Players.List 14 | 15 | 16 | view : Model -> Html Msg 17 | view model = 18 | div [] 19 | [ page model ] 20 | 21 | 22 | page : Model -> Html Msg 23 | page model = 24 | Html.map PlayersMsg (Players.List.view model.players) 25 | ``` 26 | 27 | -------------------------------------------------------------------------------- /en-v01/05-resources/06-main.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Main 4 | 5 | Finally modify __src/Main.elm__ to call `initialModel`: 6 | 7 | ```elm 8 | module Main exposing (..) 9 | 10 | import Html exposing (Html, div, text, program) 11 | import Messages exposing (Msg) 12 | import Models exposing (Model, initialModel) 13 | import Update exposing (update) 14 | import View exposing (view) 15 | 16 | 17 | init : ( Model, Cmd Msg ) 18 | init = 19 | ( initialModel, Cmd.none ) 20 | 21 | 22 | subscriptions : Model -> Sub Msg 23 | subscriptions model = 24 | Sub.none 25 | 26 | -- MAIN 27 | 28 | main : Program Never Model Msg 29 | main = 30 | program 31 | { init = init 32 | , view = view 33 | , update = update 34 | , subscriptions = subscriptions 35 | } 36 | ``` 37 | 38 | Here we added `initialModel` in the import and `init`. 39 | 40 | --- 41 | 42 | When you run the application you should see a list with one user. 43 | 44 | ![Screenshot](screenshot.png) 45 | 46 | The application should look like 47 | 48 | -------------------------------------------------------------------------------- /en-v01/05-resources/cover.md: -------------------------------------------------------------------------------- 1 | # Resources 2 | 3 | Up to this point your code should look like 4 | 5 | In this chapter we will add the first resource to our application: Players. 6 | -------------------------------------------------------------------------------- /en-v01/05-resources/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v01/05-resources/screenshot.png -------------------------------------------------------------------------------- /en-v01/06-fetching-resources/01-plan.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Plan 4 | 5 | The next step is to fetch the list of players from the fake API we created before. 6 | 7 | This is the plan: 8 | 9 | ![Plan](01-plan.png) 10 | 11 | (1-2) When the application loads, we trigger a command to initiate an Http request to fetch the players. This will be done in the `init` of Html.program. 12 | 13 | (3-6) When the request is done, we trigger a `FetchAllDone` with the data, this message flows down to `Players.Update` which updates the collection of players. 14 | 15 | (7-10) Then the application renders with the updated players' list. 16 | 17 | ## Dependencies 18 | 19 | We will need the `http`, install it using: 20 | 21 | ```bash 22 | elm package install elm-lang/http 23 | ``` 24 | -------------------------------------------------------------------------------- /en-v01/06-fetching-resources/01-plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v01/06-fetching-resources/01-plan.png -------------------------------------------------------------------------------- /en-v01/06-fetching-resources/01-plan.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant program #white 6 | participant init #white 7 | participant Main.Update as MU #white 8 | participant Main.View as MV #white 9 | participant Players.Update as PU #white 10 | participant Players.List as PL #white 11 | 12 | program -> init 13 | init --> program : fetchAll 14 | program -> MU : (model, PlayersMsg (FetchAllDone players)) 15 | MU -> PU : (currentPlayers, FetchAllDone players) 16 | PU --> MU : Updated players' collection 17 | MU --> program : Updated app model 18 | program -> MV : App model 19 | MV -> PL : Players 20 | PL --> MV :Rendered view 21 | MV --> program : Rendered view 22 | @enduml 23 | -------------------------------------------------------------------------------- /en-v01/06-fetching-resources/02-players-messages.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Players messages 4 | 5 | First let's create the messages we need for fetching players. Add a new import and message to __src/Players/Messages.elm__ 6 | 7 | ```elm 8 | module Players.Messages exposing (..) 9 | 10 | import Http 11 | import Players.Models exposing (PlayerId, Player) 12 | 13 | 14 | type Msg 15 | = OnFetchAll (Result Http.Error (List Player)) 16 | ``` 17 | 18 | `OnFetchAll` will be called when we get the response from the server. This message will carry a `Result` which can be either an `Http.Error` or the the list of fetched players. 19 | -------------------------------------------------------------------------------- /en-v01/06-fetching-resources/03-players-update.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Players Update 4 | 5 | When the request for players is done, we trigger the `OnFetchAll` message. 6 | 7 | __src/Players/Update.elm__ should account for this new message. Change `update` to: 8 | 9 | ```elm 10 | ... 11 | update : Msg -> List Player -> ( List Player, Cmd Msg ) 12 | update message players = 13 | case message of 14 | OnFetchAll (Ok newPlayers) -> 15 | ( newPlayers, Cmd.none ) 16 | 17 | OnFetchAll (Err error) -> 18 | ( players, Cmd.none ) 19 | ``` 20 | 21 | When we get `OnFetchAll` we can use pattern matching to decide what to do. 22 | 23 | - In the `Ok` case we return the fetched players in order to update the players collection. 24 | - In the `Err` case we just return what we had before for now (A better approach would be to show an error to the user, but for simplicity of the tutorial we won't be doing this now). 25 | -------------------------------------------------------------------------------- /en-v01/06-fetching-resources/05-main.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Main 4 | 5 | ## Main Model 6 | 7 | Remove the hardcoded list of players in __src/Models.elm__ 8 | 9 | ```elm 10 | initialModel : Model 11 | initialModel = 12 | { players = [] 13 | } 14 | ``` 15 | 16 | ## Main 17 | 18 | Finally, we want to run the `fetchAll` when starting the application. 19 | 20 | Update __src/Main.elm__: 21 | 22 | ```elm 23 | ... 24 | import Messages exposing (Msg(..)) 25 | ... 26 | import Players.Commands exposing (fetchAll) 27 | 28 | init : ( Model, Cmd Msg ) 29 | init = 30 | ( initialModel, Cmd.map PlayersMsg fetchAll ) 31 | ``` 32 | 33 | Now `init` returns a list of commands to run when the application starts. 34 | -------------------------------------------------------------------------------- /en-v01/06-fetching-resources/06-try-it.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Try it 4 | 5 | Try it! Run the app in one terminal using: 6 | 7 | ```bash 8 | nf start 9 | ``` 10 | 11 | Refresh the browser, our application should now fetch the list of players from the server. The app should look like: 12 | 13 | ![Screenshot](screenshot.png) 14 | 15 | Your application code should look at this stage like . 16 | -------------------------------------------------------------------------------- /en-v01/06-fetching-resources/cover.md: -------------------------------------------------------------------------------- 1 | # Fetching resources 2 | 3 | This chapter covers fetching the players' collection from the fake API. 4 | 5 | Up to this point your application code looks like 6 | -------------------------------------------------------------------------------- /en-v01/06-fetching-resources/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v01/06-fetching-resources/screenshot.png -------------------------------------------------------------------------------- /en-v01/07-routing/01-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v01/07-routing/01-intro.png -------------------------------------------------------------------------------- /en-v01/07-routing/01-intro.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant Browser #white 6 | participant Navigation #white 7 | participant init #white 8 | participant update #white 9 | participant parseLocation #white 10 | participant View #white 11 | 12 | Navigation -> init : Current location 13 | init -> parseLocation : Location 14 | parseLocation --> init : Matched Route 15 | init --> Navigation : Initial model 16 | Navigation -> View : Model 17 | View --> Navigation : Rendered view 18 | 19 | newpage 20 | 21 | autonumber 1 "(#)" 22 | Browser -> Navigation : Location change event 23 | Navigation -> update : OnLocationChange 24 | update -> parseLocation : Location 25 | parseLocation --> update : Matched Route 26 | update --> Navigation : Updated model 27 | Navigation -> View : Model 28 | View --> Navigation : Rendered view 29 | 30 | @enduml 31 | 32 | -------------------------------------------------------------------------------- /en-v01/07-routing/01-intro_001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v01/07-routing/01-intro_001.png -------------------------------------------------------------------------------- /en-v01/07-routing/04-main-model.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Main model 4 | 5 | In our main application model we want to store the current route. 6 | Change __src/Models.elm__ to: 7 | 8 | ```elm 9 | module Models exposing (..) 10 | 11 | import Players.Models exposing (Player) 12 | import Routing 13 | 14 | 15 | type alias Model = 16 | { players : List Player 17 | , route : Routing.Route 18 | } 19 | 20 | 21 | initialModel : Routing.Route -> Model 22 | initialModel route = 23 | { players = [] 24 | , route = route 25 | } 26 | ``` 27 | 28 | Here we: 29 | 30 | - added `route` to the model 31 | - changed `initialModel` so it takes a `route` 32 | -------------------------------------------------------------------------------- /en-v01/07-routing/05-main-messages.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Main messages 4 | 5 | When the browser location changes we will trigger a new message. 6 | 7 | Change __src/Messages.elm__ to: 8 | 9 | ```elm 10 | module Messages exposing (..) 11 | 12 | import Navigation exposing (Location) 13 | import Players.Messages 14 | 15 | 16 | type Msg 17 | = PlayersMsg Players.Messages.Msg 18 | | OnLocationChange Location 19 | ``` 20 | 21 | - We are now importing `Navigation` 22 | - And we added a `OnLocationChange Location` message -------------------------------------------------------------------------------- /en-v01/07-routing/06-main-update.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Main update 4 | 5 | We need our main `update` function to respond to the new `OnLocationChange` message. 6 | 7 | In __src/Update.elm__ add a new branch: 8 | 9 | ```elm 10 | ... 11 | import Routing exposing (parseLocation) 12 | 13 | ... 14 | 15 | update msg model = 16 | case msg of 17 | ... 18 | OnLocationChange location -> 19 | let 20 | newRoute = 21 | parseLocation location 22 | in 23 | ( { model | route = newRoute }, Cmd.none ) 24 | ``` 25 | 26 | Here when we receive the `OnLocationChange` message, we parse this location and store the matched route in the model. -------------------------------------------------------------------------------- /en-v01/07-routing/09-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v01/07-routing/09-edit.png -------------------------------------------------------------------------------- /en-v01/07-routing/09-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v01/07-routing/09-list.png -------------------------------------------------------------------------------- /en-v01/07-routing/09-try-it.md: -------------------------------------------------------------------------------- 1 | # Try it 2 | 3 | Let's try what we have so far. Run the application by doing: 4 | 5 | ```bash 6 | nf start 7 | ``` 8 | 9 | Then go to `http://localhost:3000` in your browser. You should see the list of users. 10 | 11 | ![screenshot](09-list.png) 12 | 13 | If you go to `http://localhost:3000/#players/2` then you should see one user. 14 | 15 | ![screenshot](09-edit.png) 16 | 17 | Next we will add some navigation. 18 | 19 | Up to this point your application code should look . 20 | 21 | -------------------------------------------------------------------------------- /en-v01/07-routing/cover.md: -------------------------------------------------------------------------------- 1 | # Routing 2 | 3 | This chapter covers adding routing to our application. 4 | 5 | Up to this point the application code looks like 6 | -------------------------------------------------------------------------------- /en-v01/08-edit/01-plan.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Plan 4 | 5 | The plan for changing a player's level is as follows: 6 | 7 | ![Flow](01-plan.png) 8 | 9 | (1) When the user clicks the increase or decrease button we trigger a message `ChangeLevel` with the `playerId` and `howMuch` as payload. 10 | 11 | (2) __Html.program__ (which Navigation wraps) will send this message back to `Main.Update` which will route it to `Players.Update` (3). 12 | 13 | (4) `Players.Update` will return a command to save the player, this command flows up to __Html.program__ (5). 14 | 15 | (6) The Elm runtime executes the command (trigger an API call) and we will get a result back, either a succesful save or a failure. In the success case we trigger a `SaveSuccess` message with the updated player as payload. 16 | 17 | (7) `Main.Update` routes the `SaveSuccess` message to `Players.Update`. 18 | 19 | (8) In `Players.Update` we update the `players` model and return it. This flows back to Html.program (9). 20 | 21 | (10) Then Html.program will render the application with the updated model. 22 | -------------------------------------------------------------------------------- /en-v01/08-edit/01-plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v01/08-edit/01-plan.png -------------------------------------------------------------------------------- /en-v01/08-edit/01-plan.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant Html.program as program #white 6 | participant Main.Update as MU #white 7 | participant Main.View as MV #white 8 | participant Players.Update as PU #white 9 | participant Players.Edit as PE #white 10 | 11 | PE -> program : PlayersMsg (ChangeLevel playerId howMuch) 12 | program -> MU : PlayersMsg (ChangeLevel playerId howMuch) 13 | MU -> PU : ChangeLevel playerId howMuch 14 | PU --> MU : Command to save 15 | MU --> program : Command to save 16 | ||| 17 | program -> MU : PlayersMsg (SaveSuccess player) 18 | MU -> PU : (SaveSuccess player) 19 | PU --> MU : Updated players 20 | MU --> program : Updated model 21 | program -> MV : Updated model 22 | 23 | 24 | @enduml 25 | 26 | -------------------------------------------------------------------------------- /en-v01/08-edit/02-messages.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Messages 4 | 5 | Let's start by adding the messages we will need. 6 | 7 | In __src/Players/Messages.elm__ add: 8 | 9 | ```elm 10 | type Msg 11 | ... 12 | | ChangeLevel PlayerId Int 13 | | OnSave (Result Http.Error Player) 14 | ``` 15 | 16 | - `ChangeLevel` will trigger when the user wants to change the level. The second parameter is an integer that indicates how much to change the level e.g. -1 to decrease or 1 to increase. 17 | - Then we will send a request to update the player to the API. `OnSave` will be triggered after the response from the API is received. 18 | - `OnSave` will either carry the updated player on success or the Http error on failure. 19 | -------------------------------------------------------------------------------- /en-v01/08-edit/03-player-edit.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | ## Player edit view 4 | 5 | We created a `ChangeLevel` message. Let's trigger this message from the player's edit view. 6 | 7 | In __src/Players/Edit.elm__ change `btnLevelDecrease` and `btnLevelIncrease`: 8 | 9 | ```elm 10 | ... 11 | btnLevelDecrease : Player -> Html Msg 12 | btnLevelDecrease player = 13 | a [ class "btn ml1 h1", onClick (ChangeLevel player.id -1) ] 14 | [ i [ class "fa fa-minus-circle" ] [] ] 15 | 16 | 17 | btnLevelIncrease : Player -> Html Msg 18 | btnLevelIncrease player = 19 | a [ class "btn ml1 h1", onClick (ChangeLevel player.id 1) ] 20 | [ i [ class "fa fa-plus-circle" ] [] ] 21 | ``` 22 | 23 | In these two buttons we added `onClick (ChangeLevel player.id howMuch)`. Where `howMuch` is `-1` to decrease level and `1` to increase it. 24 | -------------------------------------------------------------------------------- /en-v01/08-edit/cover.md: -------------------------------------------------------------------------------- 1 | # Edit 2 | 3 | In this last chapter of the tutorial we will edit a player's level and save it to the backend. 4 | 5 | Up to this point your application code should look like . 6 | -------------------------------------------------------------------------------- /en-v01/09-conclusion/cover.md: -------------------------------------------------------------------------------- 1 | # Conclusion 2 | 3 | This concludes this tutorial but keep reading for some ideas on improvements and features. 4 | 5 | I would like to hear your feedback to improve this tutorial. Please open issues at . 6 | 7 | Thanks! 8 | -------------------------------------------------------------------------------- /en-v01/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v01/logo.png -------------------------------------------------------------------------------- /en-v01/tips-tricks/context.md: -------------------------------------------------------------------------------- 1 | # Contexts 2 | 3 | Typical `update` or `view` functions look like: 4 | 5 | ```elm 6 | view : Model -> Html Msg 7 | view model = 8 | ... 9 | ``` 10 | 11 | Or 12 | 13 | ```elm 14 | update : Msg -> Model -> (Model, Cmd Msg) 15 | update message model = 16 | ... 17 | ``` 18 | 19 | It is very easy to get stuck in thinking that you need to pass only the `Model` that belongs to this component. Sometimes you need extra information and is perfectly fine to ask for it. For example: 20 | 21 | ```elm 22 | type alias Context = 23 | { model : Model 24 | , time : Time 25 | } 26 | 27 | view : Context -> Html Msg 28 | view context = 29 | ... 30 | ``` 31 | 32 | This function asks for the component model plus a `time` which is defined in its parent's model. 33 | 34 | -------------------------------------------------------------------------------- /en-v01/tips-tricks/troubleshooting.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting 2 | 3 | If you find some weird compiler behaviour during development try deleting `elm-stuff/build-artifacts` and compiling again, this usually fixes several issues. -------------------------------------------------------------------------------- /en-v03/01-intro/01-requirements.md: -------------------------------------------------------------------------------- 1 | # Requirements 2 | 3 | To follow this tutorial you will need: 4 | 5 | ## Elm version 0.19 6 | 7 | You can install Elm from here 8 | 9 | ## Node JS version 6 + 10 | 11 | You can install Node from -------------------------------------------------------------------------------- /en-v03/01-intro/02-foundations.md: -------------------------------------------------------------------------------- 1 | ## Foundations 2 | 3 | This version of the tutorial doesn't cover the foundations of the Elm language or the Elm architecture. Some familiarity with these is necessary to follow. 4 | 5 | The [official Elm guide](https://guide.elm-lang.org/) is an excellent place to learn the foundations. -------------------------------------------------------------------------------- /en-v03/01-intro/03-plan.md: -------------------------------------------------------------------------------- 1 | # Plan for the app 2 | 3 | We will build a basic application to track an imaginary role playing game. 4 | 5 | ### Resources 6 | 7 | During the rest of this guide I will use the word __resources__ to refer to models that are the subject of our application. These are __players__ in this application. Using the word __model__ can be confusing because component specific state is also a model (for example the expanded / collapse state of a component). 8 | 9 | ## Wireframes 10 | 11 | The application will have two views: 12 | 13 | ![Plan](03-planning.png) 14 | 15 | ### Screen 1 16 | 17 | Will show a list of players. From here you can: 18 | 19 | - Navigate to edit a player 20 | 21 | ### Screen 2 22 | 23 | Shows the edit view for a player. In this screen you can: 24 | 25 | - Change the level 26 | 27 | This is a very simple application that will demonstrate: 28 | 29 | - Multiple views 30 | - Nested components 31 | - Breaking the application into resources 32 | - Routing 33 | - Shared state across the application 34 | - Read and edit operation on the records 35 | - Ajax requests -------------------------------------------------------------------------------- /en-v03/01-intro/03-plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en-v03/01-intro/03-plan.png -------------------------------------------------------------------------------- /en-v03/02-start/01-project.md: -------------------------------------------------------------------------------- 1 | # Starting the project 2 | 3 | Let's start by creating a project for our application. 4 | 5 | Create a new directory and inside run: 6 | 7 | ``` 8 | npm init 9 | ``` 10 | 11 | And accept all the defaults. This will create a `package.json` in this directory. -------------------------------------------------------------------------------- /en-v03/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [Introduction](README.md) 4 | * [Requirements](01-intro/01-requirements.md) 5 | * [Foundations](01-intro/02-foundations.md) 6 | * [Plan](01-intro/03-plan.md) -------------------------------------------------------------------------------- /en/01-foundations/01-hello.elm: -------------------------------------------------------------------------------- 1 | module Hello exposing (..) 2 | 3 | import Html exposing (text) 4 | 5 | 6 | main = 7 | text "Hello" 8 | -------------------------------------------------------------------------------- /en/01-foundations/cover.md: -------------------------------------------------------------------------------- 1 | # Foundations 2 | 3 | This chapter covers: 4 | 5 | - Running a basic Elm application 6 | - Basic of functions and types in Elm -------------------------------------------------------------------------------- /en/02-elm-arch/01-introduction.elm: -------------------------------------------------------------------------------- 1 | module App exposing (..) 2 | 3 | import Html exposing (Html, div, text, program) 4 | 5 | 6 | -- MODEL 7 | 8 | 9 | type alias Model = 10 | String 11 | 12 | 13 | init : ( Model, Cmd Msg ) 14 | init = 15 | ( "Hello", Cmd.none ) 16 | 17 | 18 | 19 | -- MESSAGES 20 | 21 | 22 | type Msg 23 | = NoOp 24 | 25 | 26 | 27 | -- VIEW 28 | 29 | 30 | view : Model -> Html Msg 31 | view model = 32 | div [] 33 | [ text model ] 34 | 35 | 36 | 37 | -- UPDATE 38 | 39 | 40 | update : Msg -> Model -> ( Model, Cmd Msg ) 41 | update msg model = 42 | case msg of 43 | NoOp -> 44 | ( model, Cmd.none ) 45 | 46 | 47 | 48 | -- SUBSCRIPTIONS 49 | 50 | 51 | subscriptions : Model -> Sub Msg 52 | subscriptions model = 53 | Sub.none 54 | 55 | 56 | 57 | -- MAIN 58 | 59 | 60 | main : Program Never Model Msg 61 | main = 62 | program 63 | { init = init 64 | , view = view 65 | , update = update 66 | , subscriptions = subscriptions 67 | } 68 | -------------------------------------------------------------------------------- /en/02-elm-arch/04-flow.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Application flow 4 | 5 | The following diagram illustrates how the pieces of our application interact with Html.program. 6 | 7 | ![Flow](04-flow.png) 8 | 9 | 1. `Html.program` calls our view function with the initial model and renders it. 10 | 1. When the user clicks on the Expand button, the view triggers the `Expand` message. 11 | 1. `Html.program` receives the `Expand` message which calls our `update` function with `Expand` and the current application state. 12 | 1. The update function responds to the message by returning the updated state and a command to run (or `Cmd.none`). 13 | 1. `Html.program` receives the updated state, stores it, and calls the view with the updated state. 14 | 15 | Usually `Html.program` is the only place where an Elm application holds state, it is centralised in one big state tree. 16 | -------------------------------------------------------------------------------- /en/02-elm-arch/04-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en/02-elm-arch/04-flow.png -------------------------------------------------------------------------------- /en/02-elm-arch/04-flow.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber 3 | participant program #white 4 | participant update #white 5 | participant view #white 6 | 7 | program -> view : Render view 8 | ||| 9 | view -> program : Trigger message e.g. Expand 10 | program -> update : Send message with the current state 11 | update --> program : Return updated state and command 12 | program -> view : Render view 13 | @enduml 14 | -------------------------------------------------------------------------------- /en/02-elm-arch/05-msg-payload.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (Html, button, div, text, program) 4 | import Html.Events exposing (onClick) 5 | 6 | 7 | -- MODEL 8 | 9 | 10 | type alias Model = 11 | Int 12 | 13 | 14 | init : ( Model, Cmd Msg ) 15 | init = 16 | ( 0, Cmd.none ) 17 | 18 | 19 | 20 | -- MESSAGES 21 | 22 | 23 | type Msg 24 | = Increment Int 25 | 26 | 27 | 28 | -- VIEW 29 | 30 | 31 | view : Model -> Html Msg 32 | view model = 33 | div [] 34 | [ button [ onClick (Increment 2) ] [ text "+" ] 35 | , text (toString model) 36 | ] 37 | 38 | 39 | 40 | -- UPDATE 41 | 42 | 43 | update : Msg -> Model -> ( Model, Cmd Msg ) 44 | update msg model = 45 | case msg of 46 | Increment howMuch -> 47 | ( model + howMuch, Cmd.none ) 48 | 49 | 50 | 51 | -- SUBSCRIPTIONS 52 | 53 | 54 | subscriptions : Model -> Sub Msg 55 | subscriptions model = 56 | Sub.none 57 | 58 | 59 | 60 | -- MAIN 61 | 62 | 63 | main : Program Never Model Msg 64 | main = 65 | program 66 | { init = init 67 | , view = view 68 | , update = update 69 | , subscriptions = subscriptions 70 | } 71 | -------------------------------------------------------------------------------- /en/02-elm-arch/cover.md: -------------------------------------------------------------------------------- 1 | # The Elm architecture 2 | 3 | This chapter covers: 4 | 5 | - Overview of the Elm architecture 6 | - Introduction to Html.program 7 | - Messages 8 | - Commands 9 | - Subscriptions -------------------------------------------------------------------------------- /en/03-subs-cmds/02-commands.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (Html, div, button, text, program) 4 | import Html.Events exposing (onClick) 5 | import Random 6 | 7 | 8 | -- MODEL 9 | 10 | 11 | type alias Model = 12 | Int 13 | 14 | 15 | init : ( Model, Cmd Msg ) 16 | init = 17 | ( 1, Cmd.none ) 18 | 19 | 20 | 21 | -- MESSAGES 22 | 23 | 24 | type Msg 25 | = Roll 26 | | OnResult Int 27 | 28 | 29 | 30 | -- VIEW 31 | 32 | 33 | view : Model -> Html Msg 34 | view model = 35 | div [] 36 | [ button [ onClick Roll ] [ text "Roll" ] 37 | , text (toString model) 38 | ] 39 | 40 | 41 | 42 | -- UPDATE 43 | 44 | 45 | update : Msg -> Model -> ( Model, Cmd Msg ) 46 | update msg model = 47 | case msg of 48 | Roll -> 49 | ( model, Random.generate OnResult (Random.int 1 6) ) 50 | 51 | OnResult res -> 52 | ( res, Cmd.none ) 53 | 54 | 55 | 56 | -- MAIN 57 | 58 | 59 | main : Program Never Model Msg 60 | main = 61 | program 62 | { init = init 63 | , view = view 64 | , update = update 65 | , subscriptions = (always Sub.none) 66 | } 67 | -------------------------------------------------------------------------------- /en/03-subs-cmds/02-commands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en/03-subs-cmds/02-commands.png -------------------------------------------------------------------------------- /en/03-subs-cmds/02-commands.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber "(#)" 3 | 4 | participant program #white 5 | participant Main.update as MU #white 6 | participant Child.update as CU #white 7 | participant GrandChild.update as GC #white 8 | 9 | program -> MU: update 10 | MU -> CU: update 11 | CU -> GC: update 12 | GC --> CU: (model, command) 13 | CU --> MU: (model, command) 14 | MU -> program : (model, command) 15 | 16 | @enduml 17 | -------------------------------------------------------------------------------- /en/03-subs-cmds/cover.md: -------------------------------------------------------------------------------- 1 | # Subscriptions and Commands 2 | 3 | In order to listen to external input and create __side effects__ in our application we need to learn about __Subscriptions__ and __Commands__. 4 | 5 | This chapter covers: 6 | 7 | - Subscriptions 8 | - Commands 9 | -------------------------------------------------------------------------------- /en/04-starting/01-planning.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Planning 4 | 5 | We will build a basic application to track an imaginary role playing game. 6 | 7 | ### Resources 8 | 9 | During the rest of this guide I will use the word __resources__ to refer to models that are the subject of our application. These are __players__ in this application. Using the word __model__ can be confusing because component specific state is also a model (for example the expanded / collapse state of a component). 10 | 11 | ## Wireframes 12 | 13 | The application will have two views: 14 | 15 | ![Plan](01-planning.png) 16 | 17 | ### Screen 1 18 | 19 | Will show a list of players. From here you can: 20 | 21 | - Navigate to edit a player 22 | 23 | ### Screen 2 24 | 25 | Shows the edit view for a player. In this screen you can: 26 | 27 | - Change the level 28 | 29 | This is a very simple application that will demonstrate: 30 | 31 | - Multiple views 32 | - Nested components 33 | - Breaking the application into resources 34 | - Routing 35 | - Shared state across the application 36 | - Read and edit operation on the records 37 | - Ajax requests -------------------------------------------------------------------------------- /en/04-starting/01-planning.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en/04-starting/01-planning.odg -------------------------------------------------------------------------------- /en/04-starting/01-planning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en/04-starting/01-planning.png -------------------------------------------------------------------------------- /en/04-starting/05-webpack-3.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Webpack 3 4 | 5 | ## Initial Elm app 6 | 7 | Create a basic Elm app. In __src/Main.elm__: 8 | 9 | ```elm 10 | module Main exposing (..) 11 | 12 | import Html exposing (Html, div, text, program) 13 | 14 | 15 | -- MODEL 16 | 17 | 18 | type alias Model = 19 | String 20 | 21 | 22 | init : ( Model, Cmd Msg ) 23 | init = 24 | ( "Hello", Cmd.none ) 25 | 26 | 27 | 28 | -- MESSAGES 29 | 30 | 31 | type Msg 32 | = NoOp 33 | 34 | 35 | 36 | -- VIEW 37 | 38 | 39 | view : Model -> Html Msg 40 | view model = 41 | div [] 42 | [ text model ] 43 | 44 | 45 | 46 | -- UPDATE 47 | 48 | 49 | update : Msg -> Model -> ( Model, Cmd Msg ) 50 | update msg model = 51 | case msg of 52 | NoOp -> 53 | ( model, Cmd.none ) 54 | 55 | 56 | 57 | -- SUBSCRIPTIONS 58 | 59 | 60 | subscriptions : Model -> Sub Msg 61 | subscriptions model = 62 | Sub.none 63 | 64 | 65 | 66 | -- MAIN 67 | 68 | 69 | main : Program Never Model Msg 70 | main = 71 | program 72 | { init = init 73 | , view = view 74 | , update = update 75 | , subscriptions = subscriptions 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /en/04-starting/cover.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Starting an application 4 | 5 | In this chapter we start building an example Elm application. 6 | 7 | This tutorial will cover the following aspects about building an application: 8 | 9 | - Application structure 10 | - Fetching resources 11 | - Views 12 | - Routing 13 | - User interaction and saving changes 14 | 15 | See next page for details about the application. -------------------------------------------------------------------------------- /en/05-resources/01-intro.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # The Players resource 4 | 5 | We will organise our application structure by the name of the resources in our application. In this app, we only have one resource (`Players`) so there will be only a `Players` directory. 6 | 7 | The `Players` directory will contain the views for players: A list and a edit view. Each view will have its own Elm module: 8 | 9 | - Players/List.elm 10 | - Players/Edit.elm 11 | 12 | -------------------------------------------------------------------------------- /en/05-resources/02-models.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | ## Players Model 4 | 5 | Change __src/Models.elm__ to: 6 | 7 | ```elm 8 | module Models exposing (..) 9 | 10 | 11 | type alias Model = 12 | { players : List Player 13 | } 14 | 15 | 16 | initialModel : Model 17 | initialModel = 18 | { players = [ Player "1" "Sam" 1 ] 19 | } 20 | 21 | 22 | type alias PlayerId = 23 | String 24 | 25 | 26 | type alias Player = 27 | { id : PlayerId 28 | , name : String 29 | , level : Int 30 | } 31 | ``` 32 | 33 | Here we define how a player record looks. It has an id, a name and a level. 34 | 35 | Also note the definition for `PlayerId`, it is just an alias to `String`, doing this is useful for clarity later on when we have function that takes many ids. For example: 36 | 37 | ```elm 38 | addPerkToPlayer : Int -> String -> Player 39 | ``` 40 | 41 | is much clearer when written as: 42 | 43 | ```elm 44 | addPerkToPlayer : PerkId -> PlayerId -> Player 45 | ``` 46 | 47 | We also added `players` to our main model and created a hardcoded list for now. 48 | 49 | -------------------------------------------------------------------------------- /en/05-resources/03-main.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Main 4 | 5 | We want to use the `initialModel` we created before. Modify __src/Main.elm__ to use this: 6 | 7 | ```elm 8 | module Main exposing (..) 9 | 10 | import Html exposing (program) 11 | import Msgs exposing (Msg) 12 | import Models exposing (Model, initialModel) 13 | import Update exposing (update) 14 | import View exposing (view) 15 | 16 | 17 | init : ( Model, Cmd Msg ) 18 | init = 19 | ( initialModel, Cmd.none ) 20 | 21 | 22 | subscriptions : Model -> Sub Msg 23 | subscriptions model = 24 | Sub.none 25 | 26 | 27 | 28 | -- MAIN 29 | 30 | 31 | main : Program Never Model Msg 32 | main = 33 | program 34 | { init = init 35 | , view = view 36 | , update = update 37 | , subscriptions = subscriptions 38 | } 39 | ``` 40 | 41 | Here we added `initialModel` in the import and `init`. 42 | -------------------------------------------------------------------------------- /en/05-resources/05-main-view.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Main View 4 | 5 | Modify __src/View.elm__ to include the list of players: 6 | 7 | ```elm 8 | module View exposing (..) 9 | 10 | import Html exposing (Html, div, text) 11 | import Msgs exposing (Msg) 12 | import Models exposing (Model) 13 | import Players.List 14 | 15 | 16 | view : Model -> Html Msg 17 | view model = 18 | div [] 19 | [ page model ] 20 | 21 | 22 | page : Model -> Html Msg 23 | page model = 24 | Players.List.view model.players 25 | ``` 26 | 27 | --- 28 | 29 | When you run the application you should see a list with one user. 30 | 31 | ![Screenshot](screenshot.png) 32 | 33 | The application should look like -------------------------------------------------------------------------------- /en/05-resources/cover.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Resources 4 | 5 | Up to this point your code should look like 6 | 7 | In this chapter we will add the first resource to our application: Players. 8 | -------------------------------------------------------------------------------- /en/05-resources/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en/05-resources/screenshot.png -------------------------------------------------------------------------------- /en/06-fetching-resources/01-plan.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Plan 4 | 5 | The next step is to fetch the list of players from the fake API we created before. 6 | 7 | This is the plan: 8 | 9 | ![Plan](01-plan.png) 10 | 11 | (1-2) When the application loads, we trigger a command to initiate an Http request to fetch the players. This will be done in the `init` of Html.program. 12 | 13 | (3-4) When the request is done, we trigger a `OnFetchPlayers` with the response, this message flows to `Update` which updates the model by storing the response. 14 | 15 | (5) Then the application renders with the updated players' list. 16 | 17 | ## Dependencies 18 | 19 | We will need a few new packages, install them using: 20 | 21 | ```bash 22 | elm-package install elm-lang/http 23 | elm-package install NoRedInk/elm-decode-pipeline 24 | elm-package install krisajenkins/remotedata 25 | ``` 26 | 27 | - `elm-lang/http` is used for sending http requests. 28 | - `NoRedInk/elm-decode-pipeline` offers and alternative and cleaner API for decoding JSON. 29 | - `krisajenkins/remotedata` offers a robust pattern for handling remote resources, we will talk more about this later. 30 | -------------------------------------------------------------------------------- /en/06-fetching-resources/01-plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en/06-fetching-resources/01-plan.png -------------------------------------------------------------------------------- /en/06-fetching-resources/01-plan.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant program #white 6 | participant init #white 7 | participant Update #white 8 | participant View #white 9 | 10 | program -> init 11 | init --> program : fetchPlayers 12 | program -> Update : (model, OnFetchPlayers response) 13 | Update --> program : updated model with response 14 | program -> View : model 15 | @enduml 16 | -------------------------------------------------------------------------------- /en/06-fetching-resources/02-messages.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Messages 4 | 5 | First let's create the messages we need for fetching players. Add a new import and message to __src/Msgs.elm__ 6 | 7 | ```elm 8 | module Msgs exposing (..) 9 | 10 | import Models exposing (Player) 11 | import RemoteData exposing (WebData) 12 | 13 | 14 | type Msg 15 | = OnFetchPlayers (WebData (List Player)) 16 | ``` 17 | 18 | `OnFetchPlayers` will be called when we get the response from the server. This message will carry a `WebData (List Player)`. 19 | 20 | `WebData` is a type that provides four constructors: `NotAsked`, `Loading`, `Success` and `Failure`. These four possible constructors describe all states in which an HTTP resource could be. Read more about this [here](http://blog.jenkster.com/2016/06/how-elm-slays-a-ui-antipattern.html). -------------------------------------------------------------------------------- /en/06-fetching-resources/03-models.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Models 4 | 5 | We want to store the response from the server in the models instead of the hardcoded list of players we have now. 6 | In __src/Models.elm__, include a new import and change the type of `players`: 7 | 8 | ```elm 9 | ... 10 | 11 | import RemoteData exposing (WebData) 12 | 13 | 14 | type alias Model = 15 | { players : WebData (List Player) 16 | } 17 | 18 | 19 | initialModel : Model 20 | initialModel = 21 | { players = RemoteData.Loading 22 | } 23 | 24 | 25 | ... 26 | ``` 27 | 28 | - We changed the type of `players` from `List Player` to `WebData (List Player)`. This type `WebData` will contain the list of players when we get a successful response from the API. 29 | - Our initial `players` attribute will be `RemoteData.Loading`, as it says this indicates that the resource is loading. -------------------------------------------------------------------------------- /en/06-fetching-resources/05-update.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Update 4 | 5 | When the request for players is done, we trigger the `OnFetchPlayers` message. 6 | 7 | __src/Update.elm__ should account for this new message. Change `update` to: 8 | 9 | ```elm 10 | module Update exposing (..) 11 | 12 | import Msgs exposing (Msg) 13 | import Models exposing (Model) 14 | 15 | 16 | update : Msg -> Model -> ( Model, Cmd Msg ) 17 | update msg model = 18 | case msg of 19 | Msgs.OnFetchPlayers response -> 20 | ( { model | players = response }, Cmd.none ) 21 | ``` 22 | 23 | When we get `OnFetchPlayers` we get a response and store it in `players`. 24 | -------------------------------------------------------------------------------- /en/06-fetching-resources/07-try-it.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Try it 4 | 5 | Try it! Run the app in one terminal using: 6 | 7 | ```bash 8 | yarn start 9 | ``` 10 | 11 | Refresh the browser, our application should now fetch the list of players from the server. The app should look like: 12 | 13 | ![Screenshot](screenshot.png) 14 | 15 | Your application code should look at this stage like . 16 | -------------------------------------------------------------------------------- /en/06-fetching-resources/checklist.md: -------------------------------------------------------------------------------- 1 | https://github.com/sporto/elm-tutorial-app/compare/018-v02-04-resources...018-v02-05-fetch 2 | 3 | ✔ package 4 | ✔ commands 5 | ✔ main 6 | ✔ models 7 | ✔ msgs 8 | ✔ list 9 | ✔ update -------------------------------------------------------------------------------- /en/06-fetching-resources/cover.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Fetching resources 4 | 5 | This chapter covers fetching the players' collection from the fake API. 6 | 7 | Up to this point your application code looks like 8 | -------------------------------------------------------------------------------- /en/06-fetching-resources/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en/06-fetching-resources/screenshot.png -------------------------------------------------------------------------------- /en/07-routing/01-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en/07-routing/01-intro.png -------------------------------------------------------------------------------- /en/07-routing/01-intro.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant Browser #white 6 | participant Navigation #white 7 | participant init #white 8 | participant update #white 9 | participant parseLocation #white 10 | participant View #white 11 | 12 | Navigation -> init : Current location 13 | init -> parseLocation : Location 14 | parseLocation --> init : Matched Route 15 | init --> Navigation : Initial model 16 | Navigation -> View : Model 17 | View --> Navigation : Rendered view 18 | 19 | newpage 20 | 21 | autonumber 1 "(#)" 22 | Browser -> Navigation : Location change event 23 | Navigation -> update : OnLocationChange 24 | update -> parseLocation : Location 25 | parseLocation --> update : Matched Route 26 | update --> Navigation : Updated model 27 | Navigation -> View : Model 28 | View --> Navigation : Rendered view 29 | 30 | @enduml 31 | 32 | -------------------------------------------------------------------------------- /en/07-routing/01-intro_001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en/07-routing/01-intro_001.png -------------------------------------------------------------------------------- /en/07-routing/04-models.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Main model 4 | 5 | In our main application model we want to store the current route. 6 | In __src/Models.elm__, change `Model` and `initialModel` to: 7 | 8 | ```elm 9 | ... 10 | 11 | type alias Model = 12 | { players : WebData (List Player) 13 | , route : Route 14 | } 15 | 16 | 17 | initialModel : Route -> Model 18 | initialModel route = 19 | { players = RemoteData.Loading 20 | , route = route 21 | } 22 | ``` 23 | 24 | Here we: 25 | 26 | - added `route` to the model 27 | - changed `initialModel` so it takes a `route` 28 | -------------------------------------------------------------------------------- /en/07-routing/05-messages.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Messages 4 | 5 | When the browser location changes we will trigger a new `OnLocationChange` message. 6 | 7 | Change __src/Msgs.elm__ to: 8 | 9 | ```elm 10 | module Msgs exposing (..) 11 | 12 | import Models exposing (Player) 13 | import Navigation exposing (Location) 14 | import RemoteData exposing (WebData) 15 | 16 | 17 | type Msg 18 | = OnFetchPlayers (WebData (List Player)) 19 | | OnLocationChange Location 20 | ``` 21 | 22 | - We are now importing `Navigation` 23 | - And we added a `OnLocationChange Location` message -------------------------------------------------------------------------------- /en/07-routing/06-update.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Update 4 | 5 | We need our `update` function to respond to the new `OnLocationChange` message. 6 | 7 | In __src/Update.elm__ add a new branch: 8 | 9 | ```elm 10 | ... 11 | import Routing exposing (parseLocation) 12 | 13 | ... 14 | 15 | update msg model = 16 | case msg of 17 | ... 18 | Msgs.OnLocationChange location -> 19 | let 20 | newRoute = 21 | parseLocation location 22 | in 23 | ( { model | route = newRoute }, Cmd.none ) 24 | ``` 25 | 26 | Here when we receive the `OnLocationChange` message, we parse this location and store the matched route in the model. -------------------------------------------------------------------------------- /en/07-routing/09-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en/07-routing/09-edit.png -------------------------------------------------------------------------------- /en/07-routing/09-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en/07-routing/09-list.png -------------------------------------------------------------------------------- /en/07-routing/09-try-it.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Try it 4 | 5 | Let's try what we have so far. Run the application by doing: 6 | 7 | ```bash 8 | yarn start 9 | ``` 10 | 11 | Then go to `http://localhost:3000` in your browser. You should see the list of users. 12 | 13 | ![screenshot](09-list.png) 14 | 15 | If you go to `http://localhost:3000/#players/2` then you should see one user. 16 | 17 | ![screenshot](09-edit.png) 18 | 19 | Next we will add some navigation. 20 | 21 | Up to this point your application code should look . 22 | 23 | -------------------------------------------------------------------------------- /en/07-routing/11-try-it.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | ## Test it 4 | 5 | Go to the list `http://localhost:3000/#players`. You should now see an Edit button, upon clicking it the location should change to the edit view. 6 | 7 | Up to this point your application code should look . 8 | 9 | ## Navigation approaches 10 | 11 | We are using hash routing here which is simple. But it is a bit ugly because your URLs will need to include a `#`. Hash routing will also conflict if you want to use the `#` for its original intent, which is creating anchors on a page. 12 | 13 | As an alternative you can use "path" routing, which uses push state. Instead of having something like `app.com/#users` you will have `app.com/users`, which is nicer. 14 | 15 | You can use path routing in Elm using the `Navigation` module too. See [this repository for an explanation and example](https://github.com/sporto/elm-navigation-pushstate). 16 | -------------------------------------------------------------------------------- /en/07-routing/checklist.md: -------------------------------------------------------------------------------- 1 | https://github.com/sporto/elm-tutorial-app/compare/018-v02-05-fetch...018-v02-06-routing 2 | 3 | elm-package.json ✔ 4 | src/Main.elm ✔ 5 | src/Models.elm : Route types ✔ , initialModel ✔ 6 | src/Msgs.elm ✔ 7 | src/Players/Edit.elm ✔ 8 | src/Routing.elm ✔ 9 | src/Update.elm ✔ 10 | src/View.elm ✔ 11 | 12 | ## Navigation 13 | 14 | https://github.com/sporto/elm-tutorial-app/compare/018-v02-06-routing...018-v02-07-navigation -------------------------------------------------------------------------------- /en/07-routing/cover.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Routing 4 | 5 | This chapter covers adding routing to our application. 6 | 7 | Up to this point the application code looks like 8 | -------------------------------------------------------------------------------- /en/08-edit/01-plan.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Plan 4 | 5 | The plan for changing a player's level is as follows: 6 | 7 | ![Flow](01-plan.png) 8 | 9 | (1) When the user clicks the increase or decrease button we trigger a message `ChangeLevel` with the `player` and `howMuch` as payload. 10 | 11 | (2) __Html.program__ (which Navigation wraps) will send this message back to `Update`. 12 | 13 | (3) `Update` will return a command to save the player. 14 | 15 | (4) The Elm runtime executes the command (trigger an API call) and we will get a result back, which is either a successful save or a failure. In the success case we trigger a `OnPlayerSave` message with the updated player as payload. 16 | 17 | (5) In `Update` we update the `players` model and return it. 18 | 19 | (6) Then Html.program will render the application with the updated model. 20 | -------------------------------------------------------------------------------- /en/08-edit/01-plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en/08-edit/01-plan.png -------------------------------------------------------------------------------- /en/08-edit/01-plan.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant Html.program as program #white 6 | participant Update #white 7 | participant View #white 8 | participant Update #white 9 | participant View.Edit as PE #white 10 | 11 | PE -> program : ChangeLevel player howMuch 12 | program -> Update : ChangeLevel player howMuch 13 | Update --> program : Command to save 14 | ||| 15 | program -> Update : OnPlayerSave player 16 | Update --> program : Updated model 17 | program -> View : Updated model 18 | 19 | 20 | @enduml 21 | 22 | -------------------------------------------------------------------------------- /en/08-edit/02-messages.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Messages 4 | 5 | Let's start by adding the messages we will need. 6 | 7 | In __src/Msgs.elm__ add: 8 | 9 | ```elm 10 | import Http 11 | ... 12 | 13 | type Msg 14 | ... 15 | | ChangeLevel Player Int 16 | | OnPlayerSave (Result Http.Error Player) 17 | ``` 18 | 19 | - `ChangeLevel` will trigger when the user wants to change the level. The second parameter is an integer that indicates how much to change the level e.g. -1 to decrease or 1 to increase. 20 | - Then we will send a request to update the player to the API. `OnPlayerSave` will be triggered after the response from the API is received. 21 | - `OnPlayerSave` will either carry the updated player on success or the Http error on failure. 22 | -------------------------------------------------------------------------------- /en/08-edit/03-player-edit.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | ## Player edit view 4 | 5 | We created a `ChangeLevel` message. Let's trigger this message from the player's edit view. 6 | 7 | In __src/Players/Edit.elm__, first add `onClick`: 8 | 9 | ```elm 10 | import Html.Events exposing (onClick) 11 | ``` 12 | 13 | And change `btnLevelDecrease` and `btnLevelIncrease`: 14 | 15 | ```elm 16 | ... 17 | btnLevelDecrease : Player -> Html Msg 18 | btnLevelDecrease player = 19 | let 20 | message = 21 | Msgs.ChangeLevel player -1 22 | in 23 | a [ class "btn ml1 h1", onClick message ] 24 | [ i [ class "fa fa-minus-circle" ] [] ] 25 | 26 | 27 | btnLevelIncrease : Player -> Html Msg 28 | btnLevelIncrease player = 29 | let 30 | message = 31 | Msgs.ChangeLevel player 1 32 | in 33 | a [ class "btn ml1 h1", onClick message ] 34 | [ i [ class "fa fa-plus-circle" ] [] ] 35 | ``` 36 | 37 | In these two buttons we added `onClick message`. This `message` is `Msgs.ChangeLevel player howMuch`. Where `howMuch` is `-1` to decrease level and `1` to increase it. 38 | -------------------------------------------------------------------------------- /en/08-edit/checklist.md: -------------------------------------------------------------------------------- 1 | https://github.com/sporto/elm-tutorial-app/compare/018-v02-07-navigation...018-v02-08-edit 2 | 3 | Commands.elm 4 | Msgs.elm 5 | Players/Edit.elm 6 | Update.elm -------------------------------------------------------------------------------- /en/08-edit/cover.md: -------------------------------------------------------------------------------- 1 | > This page covers Tutorial v2. Elm 0.18. 2 | 3 | # Edit 4 | 5 | In this last chapter of the tutorial we will edit a player's level and save it to the backend. 6 | 7 | Up to this point your application code should look like . 8 | -------------------------------------------------------------------------------- /en/09-conclusion/cover.md: -------------------------------------------------------------------------------- 1 | # Conclusion 2 | 3 | This concludes this tutorial but keep reading for some ideas on improvements and features. 4 | 5 | I would like to hear your feedback to improve this tutorial. Please open issues at . 6 | 7 | Thanks! 8 | -------------------------------------------------------------------------------- /en/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/en/logo.png -------------------------------------------------------------------------------- /en/tips-tricks/context.md: -------------------------------------------------------------------------------- 1 | # Contexts 2 | 3 | Typical `update` or `view` functions look like: 4 | 5 | ```elm 6 | view : Model -> Html Msg 7 | view model = 8 | ... 9 | ``` 10 | 11 | Or 12 | 13 | ```elm 14 | update : Msg -> Model -> (Model, Cmd Msg) 15 | update message model = 16 | ... 17 | ``` 18 | 19 | It is very easy to get stuck in thinking that you need to pass only the `Model` that belongs to this component. Sometimes you need extra information and is perfectly fine to ask for it. For example: 20 | 21 | ```elm 22 | type alias Context = 23 | { model : Model 24 | , time : Time 25 | } 26 | 27 | view : Context -> Html Msg 28 | view context = 29 | ... 30 | ``` 31 | 32 | This function asks for the component model plus a `time` which is defined in its parent's model. 33 | 34 | -------------------------------------------------------------------------------- /en/tips-tricks/troubleshooting.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting 2 | 3 | If you find some weird compiler behaviour during development try deleting `elm-stuff/build-artifacts` and compiling again, this usually fixes several issues. -------------------------------------------------------------------------------- /es/01-fundamentos/cover.md: -------------------------------------------------------------------------------- 1 | # Fundamentos 2 | 3 | Este capítulo trata de: 4 | 5 | - Ejecución de una aplicación básica Elm 6 | - Funciones y tipos básicos en Elm 7 | -------------------------------------------------------------------------------- /es/02-elm-arch/cover.md: -------------------------------------------------------------------------------- 1 | # The Elm architecture 2 | 3 | Este capítulo aun no has sido traducido. Si deseas ayudar a traducirlo por favor ve a https://github.com/sporto/elm-tutorial -------------------------------------------------------------------------------- /es/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [Introducción](README.md) 4 | * [Fundamentos](01-fundamentos/cover.md) 5 | * [Hola Mundo](01-fundamentos/01-hola-mundo.md) 6 | * [Funciones](01-fundamentos/02-funciones.md) 7 | * [Más sobre functiones](01-fundamentos/03-functiones-2.md) 8 | * [Imports y modules](01-fundamentos/04-imports-y-modules.md) 9 | * [Tipos Union](01-fundamentos/05-tipos-union.md) 10 | * [Tipos aliases](01-fundamentos/06-tipos-aliases.md) 11 | * [Tipo unidad](01-fundamentos/07-tipos-unit.md) 12 | * [La arquitectura Elm](02-elm-arch/cover.md) -------------------------------------------------------------------------------- /es/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/es/logo.png -------------------------------------------------------------------------------- /fr/01-fondations/01-hello.elm: -------------------------------------------------------------------------------- 1 | module Hello exposing (..) 2 | 3 | import Html exposing (text) 4 | 5 | 6 | main = 7 | text "Hello" 8 | -------------------------------------------------------------------------------- /fr/01-fondations/couverture.md: -------------------------------------------------------------------------------- 1 | # Fondations 2 | 3 | Ce chapitre aborde les sujets suivants : 4 | 5 | - Exécuter une application Elm basique 6 | - Fonctions et types avec Elm : les bases 7 | -------------------------------------------------------------------------------- /fr/02-elm-arch/01-introduction.elm: -------------------------------------------------------------------------------- 1 | module App exposing (..) 2 | 3 | import Html exposing (Html, div, text, program) 4 | 5 | 6 | -- MODEL 7 | 8 | 9 | type alias Model = 10 | String 11 | 12 | 13 | init : ( Model, Cmd Msg ) 14 | init = 15 | ( "Hello", Cmd.none ) 16 | 17 | 18 | 19 | -- MESSAGES 20 | 21 | 22 | type Msg 23 | = NoOp 24 | 25 | 26 | 27 | -- VIEW 28 | 29 | 30 | view : Model -> Html Msg 31 | view model = 32 | div [] 33 | [ text model ] 34 | 35 | 36 | 37 | -- UPDATE 38 | 39 | 40 | update : Msg -> Model -> ( Model, Cmd Msg ) 41 | update msg model = 42 | case msg of 43 | NoOp -> 44 | ( model, Cmd.none ) 45 | 46 | 47 | 48 | -- SUBSCRIPTIONS 49 | 50 | 51 | subscriptions : Model -> Sub Msg 52 | subscriptions model = 53 | Sub.none 54 | 55 | 56 | 57 | -- MAIN 58 | 59 | 60 | main : Program Never Model Msg 61 | main = 62 | program 63 | { init = init 64 | , view = view 65 | , update = update 66 | , subscriptions = subscriptions 67 | } 68 | -------------------------------------------------------------------------------- /fr/02-elm-arch/04-flux.md: -------------------------------------------------------------------------------- 1 | > Cette page couvre Elm 0.18 2 | 3 | # Flux d'une application 4 | 5 | Le diagramme suivant illustre comment les pièces de notre application interagissent avec Html.program. 6 | 7 | ![Flux](04-flux.png) 8 | 9 | 1. Html.program appelle notre fonction `view` avec le modèle initial et l'affiche. 10 | 1. Lorsque l'utilisateur clique sur le bouton _Expand_, la vue déclenche le message `Expand`. 11 | 1. Html.program reçoit le message `Expand` qui appelle notre fonction `update` avec comme paramètres `Expand` et l'état actuel de notre application. 12 | 1. La fonction `update` répond au message en retournant l'état mis à jour et une commande à exécuter (ou aucune avec `Cmd.none`). 13 | 1. Html.program reçoit l'état mis à jour, le stocke, et appelle la vue avec l'état mis à jour. 14 | 15 | Habituellement, l'état d'une application Elm se trouve uniquement au sein d'`Html.program`, il est centralisé dans un grand arbre d'état. 16 | -------------------------------------------------------------------------------- /fr/02-elm-arch/04-flux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/fr/02-elm-arch/04-flux.png -------------------------------------------------------------------------------- /fr/02-elm-arch/04-flux.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber 3 | participant program #white 4 | participant update #white 5 | participant view #white 6 | 7 | program -> view : Affiche la vue 8 | ||| 9 | view -> program : Déclenche un message, i.e. Expand 10 | program -> update : Envoie le message avec l'état courant 11 | update --> program : Renvoie l'état mis à jour + des commandes 12 | program -> view : Affiche la vue 13 | @enduml 14 | -------------------------------------------------------------------------------- /fr/02-elm-arch/05-messages-et-donnees-attachees.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (Html, button, div, text, program) 4 | import Html.Events exposing (onClick) 5 | 6 | 7 | -- MODEL 8 | 9 | 10 | type alias Model = 11 | Int 12 | 13 | 14 | init : ( Model, Cmd Msg ) 15 | init = 16 | ( 0, Cmd.none ) 17 | 18 | 19 | 20 | -- MESSAGES 21 | 22 | 23 | type Msg 24 | = Increment Int 25 | 26 | 27 | 28 | -- VIEW 29 | 30 | 31 | view : Model -> Html Msg 32 | view model = 33 | div [] 34 | [ button [ onClick (Increment 2) ] [ text "+" ] 35 | , text (toString model) 36 | ] 37 | 38 | 39 | 40 | -- UPDATE 41 | 42 | 43 | update : Msg -> Model -> ( Model, Cmd Msg ) 44 | update msg model = 45 | case msg of 46 | Increment howMuch -> 47 | ( model + howMuch, Cmd.none ) 48 | 49 | 50 | 51 | -- SUBSCRIPTIONS 52 | 53 | 54 | subscriptions : Model -> Sub Msg 55 | subscriptions model = 56 | Sub.none 57 | 58 | 59 | 60 | -- MAIN 61 | 62 | 63 | main : Program Never Model Msg 64 | main = 65 | program 66 | { init = init 67 | , view = view 68 | , update = update 69 | , subscriptions = subscriptions 70 | } 71 | -------------------------------------------------------------------------------- /fr/02-elm-arch/06-composition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/fr/02-elm-arch/06-composition.png -------------------------------------------------------------------------------- /fr/02-elm-arch/06-composition.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber "(#)" 3 | participant User #white 4 | participant program #white 5 | participant Main.initialModel as Mim #white 6 | participant Main.view as MV #white 7 | participant Main.update as MU #white 8 | participant Widget.initialModel as Wim #white 9 | participant Widget.view as WV #white 10 | participant Widget.update as WU #white 11 | 12 | program -> Mim: initialModel 13 | Mim -> Wim: initialModel 14 | Wim --> Mim: widgetModel 15 | Mim --> program: mainModel 16 | program -> MV : mainModel 17 | MV -> WV : widgetModel 18 | WV --> MV : Html 19 | MV --> program : Html 20 | program -> User : Html 21 | 22 | newpage 23 | 24 | autonumber 1 "(#)" 25 | User -> WV : Click 26 | WV -> MV: Increase 27 | MV -> program: (WidgetMsg Increase) 28 | program -> MU: (WidgetMsg Increase) mainModel 29 | MU -> WU : Increase widgetModel 30 | WU --> MU: (updated widgetModel, command) 31 | MU --> program: (updated mainModel, command) 32 | program -> MV : mainModel 33 | MV -> WV : widgetModel 34 | WV --> MV : Html 35 | MV --> program : Html 36 | @enduml 37 | -------------------------------------------------------------------------------- /fr/02-elm-arch/06-composition/Widget.elm: -------------------------------------------------------------------------------- 1 | module Widget exposing (..) 2 | 3 | import Html exposing (Html, button, div, text) 4 | import Html.Events exposing (onClick) 5 | 6 | 7 | -- MODEL 8 | 9 | 10 | type alias Model = 11 | { count : Int 12 | } 13 | 14 | 15 | initialModel : Model 16 | initialModel = 17 | { count = 0 18 | } 19 | 20 | 21 | type Msg 22 | = Increase 23 | 24 | 25 | 26 | -- VIEW 27 | 28 | 29 | view : Model -> Html Msg 30 | view model = 31 | div [] 32 | [ div [] [ text (toString model.count) ] 33 | , button [ onClick Increase ] [ Html.text "Click" ] 34 | ] 35 | 36 | 37 | 38 | -- UPDATE 39 | 40 | 41 | update : Msg -> Model -> ( Model, Cmd Msg ) 42 | update message model = 43 | case message of 44 | Increase -> 45 | ( { model | count = model.count + 1 }, Cmd.none ) 46 | -------------------------------------------------------------------------------- /fr/02-elm-arch/06-composition/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 | }, 14 | "elm-version": "0.18.0 <= v < 0.19.0" 15 | } -------------------------------------------------------------------------------- /fr/02-elm-arch/06-composition_001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/fr/02-elm-arch/06-composition_001.png -------------------------------------------------------------------------------- /fr/02-elm-arch/cover.md: -------------------------------------------------------------------------------- 1 | # L'architecture Elm 2 | 3 | Ce chapitre aborde les sujets suivants : 4 | 5 | - Vue d'ensemble de l'architecture Elm 6 | - Introduction à `Html.program` 7 | - Messages 8 | - Commandes 9 | - Souscriptions 10 | -------------------------------------------------------------------------------- /fr/03-subs-cmds/02-commandes.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (Html, div, button, text, program) 4 | import Html.Events exposing (onClick) 5 | import Random 6 | 7 | 8 | -- MODEL 9 | 10 | 11 | type alias Model = 12 | Int 13 | 14 | 15 | init : ( Model, Cmd Msg ) 16 | init = 17 | ( 1, Cmd.none ) 18 | 19 | 20 | 21 | -- MESSAGES 22 | 23 | 24 | type Msg 25 | = Roll 26 | | OnResult Int 27 | 28 | 29 | 30 | -- VIEW 31 | 32 | 33 | view : Model -> Html Msg 34 | view model = 35 | div [] 36 | [ button [ onClick Roll ] [ text "Roll" ] 37 | , text (toString model) 38 | ] 39 | 40 | 41 | 42 | -- UPDATE 43 | 44 | 45 | update : Msg -> Model -> ( Model, Cmd Msg ) 46 | update msg model = 47 | case msg of 48 | Roll -> 49 | ( model, Random.generate OnResult (Random.int 1 6) ) 50 | 51 | OnResult res -> 52 | ( res, Cmd.none ) 53 | 54 | 55 | 56 | -- MAIN 57 | 58 | 59 | main : Program Never Model Msg 60 | main = 61 | program 62 | { init = init 63 | , view = view 64 | , update = update 65 | , subscriptions = (always Sub.none) 66 | } 67 | -------------------------------------------------------------------------------- /fr/03-subs-cmds/02-commandes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/fr/03-subs-cmds/02-commandes.png -------------------------------------------------------------------------------- /fr/03-subs-cmds/02-commandes.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber "(#)" 3 | 4 | participant App #white 5 | participant Main.update as MU #white 6 | participant Enfant.update as EU #white 7 | participant PetitEnfant.update as PE #white 8 | 9 | App -> MU: update 10 | MU -> EU: update 11 | EU -> PE: update 12 | PE --> EU: (model, command) 13 | EU --> MU: (model, command) 14 | MU -> App : (model, command) 15 | 16 | @enduml 17 | -------------------------------------------------------------------------------- /fr/03-subs-cmds/cover.md: -------------------------------------------------------------------------------- 1 | # Souscriptions et Commandes 2 | 3 | Pour écouter les entrées externes de notre application et créer des __effets de bord__ dans notre application, il nous faut comprendre les concepts de __Souscriptions__ (*Subscriptions*) et de __Commandes__ (*Commands*). 4 | 5 | Ce chapitre couvre : 6 | 7 | - les Souscriptions 8 | - les Commandes 9 | -------------------------------------------------------------------------------- /fr/04-commencer/01-preparation.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/fr/04-commencer/01-preparation.odg -------------------------------------------------------------------------------- /fr/04-commencer/01-preparation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/fr/04-commencer/01-preparation.png -------------------------------------------------------------------------------- /fr/04-commencer/05-webpack-3.md: -------------------------------------------------------------------------------- 1 | > Cette page couvre Elm 0.18 2 | 3 | # Webpack 3 4 | 5 | ## Application Elm initiale 6 | 7 | Créez une application Elm de base. Dans __src/Main.elm__ : 8 | 9 | ```elm 10 | module Main exposing (..) 11 | 12 | import Html exposing (Html, div, text, program) 13 | 14 | 15 | -- MODEL 16 | 17 | 18 | type alias Model = 19 | String 20 | 21 | 22 | init : ( Model, Cmd Msg ) 23 | init = 24 | ( "Hello", Cmd.none ) 25 | 26 | 27 | 28 | -- MESSAGES 29 | 30 | 31 | type Msg 32 | = NoOp 33 | 34 | 35 | 36 | -- VIEW 37 | 38 | 39 | view : Model -> Html Msg 40 | view model = 41 | div [] 42 | [ text model ] 43 | 44 | 45 | 46 | -- UPDATE 47 | 48 | 49 | update : Msg -> Model -> ( Model, Cmd Msg ) 50 | update msg model = 51 | case msg of 52 | NoOp -> 53 | ( model, Cmd.none ) 54 | 55 | 56 | 57 | -- SUBSCRIPTIONS 58 | 59 | 60 | subscriptions : Model -> Sub Msg 61 | subscriptions model = 62 | Sub.none 63 | 64 | 65 | 66 | -- MAIN 67 | 68 | 69 | main : Program Never Model Msg 70 | main = 71 | program 72 | { init = init 73 | , view = view 74 | , update = update 75 | , subscriptions = subscriptions 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /fr/04-commencer/cover.md: -------------------------------------------------------------------------------- 1 | # Commencer une application 2 | 3 | Dans ce chapitre, nous allons commencer à écrire une application Elm ! 4 | 5 | Ce tutoriel va couvrir les thèmes suivants relatifs à la construction d'une application : 6 | 7 | - structure de l'application 8 | - récupération de ressources 9 | - vues 10 | - routage 11 | - interaction avec l'utilisateur et sauvegarde des changements 12 | 13 | Nous allons présenter l'application en détail sur la page suivante. 14 | -------------------------------------------------------------------------------- /fr/05-ressources/01-intro.md: -------------------------------------------------------------------------------- 1 | # La ressource Joueurs 2 | 3 | Nous allons structurer notre application par nom de ressource. Dans cette application, nous n'avons qu'une seule ressource, les joueurs (`Players`), donc nous n'allons créer qu'un répertoire `Players`. 4 | 5 | Ce répertoire contiendra plusieurs modules, un par composant, comme le répertoire du niveau principal : 6 | 7 | - Players/Messages.elm 8 | - Players/Models.elm 9 | - Players/Update.elm 10 | 11 | Par contre, nous aurons des vues différentes pour les joueurs : la liste, et l'édition. Chaque vue aura son propre module Elm : 12 | 13 | - Players/List.elm 14 | - Players/Edit.elm 15 | 16 | -------------------------------------------------------------------------------- /fr/05-ressources/05-vue-principale.md: -------------------------------------------------------------------------------- 1 | > Cette page couvre Elm 0.18 2 | 3 | # Vue Main 4 | 5 | Modifiez __src/View.elm__ pour inclure la liste des joueurs : 6 | 7 | ```elm 8 | module View exposing (..) 9 | 10 | import Html exposing (Html, div, text) 11 | import Messages exposing (Msg(..)) 12 | import Models exposing (Model) 13 | import Players.List 14 | 15 | 16 | view : Model -> Html Msg 17 | view model = 18 | div [] 19 | [ page model ] 20 | 21 | 22 | page : Model -> Html Msg 23 | page model = 24 | Html.map PlayersMsg (Players.List.view model.players) 25 | ``` 26 | -------------------------------------------------------------------------------- /fr/05-ressources/06-main.md: -------------------------------------------------------------------------------- 1 | > Cette page couvre Elm 0.18 2 | 3 | # Main 4 | 5 | Enfin, modifiez __src/Main.elm__ pour appeler `initialModel`: 6 | 7 | ```elm 8 | module Main exposing (..) 9 | 10 | import Html exposing (Html, div, text, program) 11 | import Messages exposing (Msg) 12 | import Models exposing (Model, initialModel) 13 | import Update exposing (update) 14 | import View exposing (view) 15 | 16 | init : ( Model, Cmd Msg ) 17 | init = 18 | ( initialModel , Cmd.none ) 19 | 20 | subscriptions : Model -> Sub Msg 21 | subscriptions model = 22 | Sub.none 23 | 24 | -- MAIN 25 | 26 | main : Program Never Model Msg 27 | main = 28 | program 29 | { init = init 30 | , view = view 31 | , update = update 32 | , subscriptions = subscriptions 33 | } 34 | ``` 35 | 36 | Nous avons ajouté `initialModel` dans les imports et dans la fonction `init`. 37 | 38 | --- 39 | 40 | Quand vous exécutez l'application, une liste contenant un joueur devrait apparaître. 41 | 42 | ![Capture d'écran](capture.png) 43 | 44 | L'application devrait ressembler à cela : 45 | -------------------------------------------------------------------------------- /fr/05-ressources/capture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/fr/05-ressources/capture.png -------------------------------------------------------------------------------- /fr/05-ressources/cover.md: -------------------------------------------------------------------------------- 1 | # Ressources 2 | 3 | Jusqu'ici, votre code devrait ressembler à cela : 4 | 5 | Dans ce chapitre, nous allons ajouter la première ressource à notre application, les Joueurs. 6 | -------------------------------------------------------------------------------- /fr/06-recuperation-ressources/01-plan.md: -------------------------------------------------------------------------------- 1 | > Cette page couvre Elm 0.18 2 | 3 | # Plan 4 | 5 | La première étape est de récupérer une liste des joueurs depuis la fausse API que nous avons créée plus tôt. 6 | 7 | Voilà le plan : 8 | 9 | ![Plan](01-plan.png) 10 | 11 | (1-2) Quand l'application se charge, on déclenche une commande pour initier une requête HTTP pour récupérer les joueurs. Cela sera fait dans la fonction `init` de `Html.program`. 12 | 13 | (3-6) Quand la requête a été effectuée, on envoie un message `FetchAllDone` avec les données ; ce message arrive jusqu'à `Players.Update` qui met à jour la collection de Joueurs. 14 | 15 | (7-10) Enfin, l'application s'affiche, avec la liste des Joueurs à jour. 16 | 17 | ## Dépendances 18 | 19 | Nous aurons besoin du paquet `http`. Pour l'installer, lancez : 20 | 21 | ```bash 22 | elm package install elm-lang/http 23 | ``` 24 | -------------------------------------------------------------------------------- /fr/06-recuperation-ressources/01-plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/fr/06-recuperation-ressources/01-plan.png -------------------------------------------------------------------------------- /fr/06-recuperation-ressources/01-plan.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant program #white 6 | participant init #white 7 | participant Main.Update as MU #white 8 | participant Main.View as MV #white 9 | participant Players.Update as PU #white 10 | participant Players.List as PL #white 11 | 12 | program -> init 13 | init --> program : fetchAll 14 | program -> MU : (model, PlayersMsg (FetchAllDone players)) 15 | MU -> PU : (currentPlayers, FetchAllDone players) 16 | PU --> MU : Updated players' collection 17 | MU --> program : Updated app model 18 | program -> MV : App model 19 | MV -> PL : Players 20 | PL --> MV :Rendered view 21 | MV --> program : Rendered view 22 | @enduml 23 | -------------------------------------------------------------------------------- /fr/06-recuperation-ressources/02-messages-joueurs.md: -------------------------------------------------------------------------------- 1 | > Cette page couvre Elm 0.18 2 | 3 | # Messages Joueurs 4 | 5 | D'abord, créons les messages dont nous avons besoin pour récupérer les Joueurs. Ajoutez un nouvel import et un nouveau message à __src/Players/Messages.elm__ : 6 | 7 | ```elm 8 | module Players.Messages exposing (..) 9 | 10 | import Http 11 | import Players.Models exposing (PlayerId, Player) 12 | 13 | 14 | type Msg 15 | = OnFetchAll (Result Http.Error (List Player)) 16 | ``` 17 | 18 | `OnFetchAll` sera appelé lorsque nous recevrons une réponse du serveur. Ce message contiendra un `Result`, qui sera soit un `Http.Error` soit la liste des joueurs récupérée. 19 | -------------------------------------------------------------------------------- /fr/06-recuperation-ressources/03-mise-a-jour-joueurs.md: -------------------------------------------------------------------------------- 1 | > Cette page couvre Elm 0.18 2 | 3 | # Mise à jour Joueurs 4 | 5 | Quand la requête pour les Joueurs est réussie, on envoie le message `OnFetchAll`. 6 | 7 | __src/Players/Update.elm__ doit prendre ce message en compte. Modifiez `update` comme suit : 8 | 9 | ```elm 10 | ... 11 | update : Msg -> List Player -> ( List Player, Cmd Msg ) 12 | update message players = 13 | case message of 14 | OnFetchAll (Ok newPlayers) -> 15 | ( newPlayers, Cmd.none ) 16 | 17 | OnFetchAll (Err error) -> 18 | ( players, Cmd.none ) 19 | ``` 20 | 21 | Lorsque nous recevons le message `OnFetchAll`, nous pouvons utiliser le pattern matching pour décider la marche à suivre. 22 | 23 | Dans le cas `Ok`, nous retournons la liste des joueurs récupérés afin de mettre à jour la collection des joueurs. 24 | 25 | Dans le cas `Err`, pour l'instant, nous retournons juste la liste que nous avions auparavant. Une meilleure approche serait d'afficher un message d'erreur à l'utilisateur, mais pour garder ce tutoriel simple, nous avons choisi de ne pas le faire. 26 | -------------------------------------------------------------------------------- /fr/06-recuperation-ressources/05-main.md: -------------------------------------------------------------------------------- 1 | > Cette page couvre Elm 0.18 2 | 3 | # Main 4 | 5 | ## Modèle Main 6 | 7 | Enlevez la liste des Joueurs codée en dur dans __src/Models.elm__ : 8 | 9 | ```elm 10 | initialModel : Model 11 | initialModel = 12 | { players = [] 13 | } 14 | ``` 15 | 16 | ## Main 17 | 18 | Pour finir, on veut exécuter `fetchAll` quand l'application démarre. 19 | 20 | Changez __src/Main.elm__ comme suit : 21 | 22 | ```elm 23 | ... 24 | import Messages exposing (Msg(..)) 25 | ... 26 | import Players.Commands exposing (fetchAll) 27 | 28 | init : ( Model, Cmd Msg ) 29 | init = 30 | ( initialModel, Cmd.map PlayersMsg fetchAll ) 31 | ``` 32 | 33 | Désormais, `init` retourne une liste de commandes à exécuter lorsque l'application démarre. 34 | -------------------------------------------------------------------------------- /fr/06-recuperation-ressources/06-essayez.md: -------------------------------------------------------------------------------- 1 | > Cette page couvre Elm 0.18 2 | 3 | # Essayez 4 | 5 | Essayez vous-même ! Lancez l'application dans un terminal en exécutant : 6 | 7 | ```bash 8 | nf start 9 | ``` 10 | 11 | Rafraîchissez le navigateur : notre application devrait aller récupérer la liste des joueurs sur le serveur. L'application devrait ressembler à ça. 12 | 13 | ![Capture d'écran](capture.png) 14 | 15 | Le code de l'application devrait ressembler à cela : . 16 | -------------------------------------------------------------------------------- /fr/06-recuperation-ressources/capture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/fr/06-recuperation-ressources/capture.png -------------------------------------------------------------------------------- /fr/06-recuperation-ressources/cover.md: -------------------------------------------------------------------------------- 1 | # Récupération de ressources 2 | 3 | Ce chapitre présente comment récupérer la collection des joueurs depuis la fausse API. 4 | 5 | Jusqu'ici, votre application devrait ressembler à cela : 6 | -------------------------------------------------------------------------------- /fr/07-routage/01-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/fr/07-routage/01-intro.png -------------------------------------------------------------------------------- /fr/07-routage/01-intro.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant Browser #white 6 | participant Navigation #white 7 | participant init #white 8 | participant update #white 9 | participant parseLocation #white 10 | participant View #white 11 | 12 | Navigation -> init : Current location 13 | init -> parseLocation : Location 14 | parseLocation --> init : Matched Route 15 | init --> Navigation : Initial model 16 | Navigation -> View : Model 17 | View --> Navigation : Rendered view 18 | 19 | newpage 20 | 21 | autonumber 1 "(#)" 22 | Browser -> Navigation : Location change event 23 | Navigation -> update : OnLocationChange 24 | update -> parseLocation : Location 25 | parseLocation --> update : Matched Route 26 | update --> Navigation : Updated model 27 | Navigation -> View : Model 28 | View --> Navigation : Rendered view 29 | 30 | @enduml 31 | 32 | -------------------------------------------------------------------------------- /fr/07-routage/01-intro_001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/fr/07-routage/01-intro_001.png -------------------------------------------------------------------------------- /fr/07-routage/04-modele-main.md: -------------------------------------------------------------------------------- 1 | > Cette page couvre Elm 0.18 2 | 3 | # Modèle Main 4 | 5 | Dans notre modèle d'application principal, on veut stocker la route actuelle. 6 | 7 | Modifiez __src/Models.elm__ comme ceci : 8 | 9 | ```elm 10 | module Models exposing (..) 11 | 12 | import Players.Models exposing (Player) 13 | import Routing 14 | 15 | 16 | type alias Model = 17 | { players : List Player 18 | , route : Routing.Route 19 | } 20 | 21 | 22 | initialModel : Routing.Route -> Model 23 | initialModel route = 24 | { players = [] 25 | , route = route 26 | } 27 | ``` 28 | 29 | Nous avons : 30 | 31 | - ajouté `route` au modèle 32 | - changé `initialModel` pour qu'il prenne une `route` 33 | -------------------------------------------------------------------------------- /fr/07-routage/05-main-messages.md: -------------------------------------------------------------------------------- 1 | > Cette page couvre Elm 0.18 2 | 3 | # Messages Main 4 | 5 | Lorsque l'adresse du navigateur changera nous déclencherons un nouveau message. 6 | 7 | Changez __src/Messages.elm__ en : 8 | 9 | ```elm 10 | module Messages exposing (..) 11 | 12 | import Navigation exposing (Location) 13 | import Players.Messages 14 | 15 | 16 | type Msg 17 | = PlayersMsg Players.Messages.Msg 18 | | OnLocationChange Location 19 | ``` 20 | 21 | - Nous avons importé `Navigation` 22 | - Et nous avons ajouté un message `OnLocationChange Location` 23 | -------------------------------------------------------------------------------- /fr/07-routage/06-main-update.md: -------------------------------------------------------------------------------- 1 | > Cette page couvre Elm 0.18 2 | 3 | # Update Main 4 | 5 | Nous avons besoin que notre fonction principale `update` réponde au nouveau message `OnLocationChange`. 6 | 7 | Dans __src/Update.elm__ ajoutez une nouvelle branche : 8 | 9 | ```elm 10 | ... 11 | import Routing exposing (parseLocation) 12 | 13 | ... 14 | 15 | update msg model = 16 | case msg of 17 | ... 18 | OnLocationChange location -> 19 | let 20 | newRoute = 21 | parseLocation location 22 | in 23 | ( { model | route = newRoute }, Cmd.none ) 24 | ``` 25 | 26 | Ici, lorsque nous recevons un message `OnLocationChange`, nous analysons cette `location` et stockons la route correspondante dans le modèle. 27 | -------------------------------------------------------------------------------- /fr/07-routage/09-edition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/fr/07-routage/09-edition.png -------------------------------------------------------------------------------- /fr/07-routage/09-essayez.md: -------------------------------------------------------------------------------- 1 | # Essayez ! 2 | 3 | Essayons ce que nous avons fait jusqu'à présent. Lancez l'application en tapant : 4 | 5 | ```bash 6 | nf start 7 | ``` 8 | 9 | Ensuite, ouvrez `http://localhost:3000` dans votre navigateur. Vous devriez voir une liste d'utilisateurs. 10 | 11 | ![screenshot](09-liste.png) 12 | 13 | Si vous allez sur `http://localhost:3000/#players/2` vous devriez voir un utilisateur. 14 | 15 | ![screenshot](09-edition.png) 16 | 17 | Nous allons maintenant ajouter la navigation. 18 | 19 | À ce stade, le code de votre application devrait ressembler à ça : . 20 | -------------------------------------------------------------------------------- /fr/07-routage/09-liste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/fr/07-routage/09-liste.png -------------------------------------------------------------------------------- /fr/07-routage/cover.md: -------------------------------------------------------------------------------- 1 | # Routage 2 | 3 | Ce chapitre explique comment ajouter le routage à notre application. 4 | 5 | Pour l'instant, le code de notre application ressemble à ça : 6 | -------------------------------------------------------------------------------- /fr/08-edition/01-plan.md: -------------------------------------------------------------------------------- 1 | > Cette page couvre Elm 0.18 2 | 3 | # Plan 4 | 5 | Voici le plan pour changer le niveau d'un joueur : 6 | 7 | ![Flow](01-plan.png) 8 | 9 | (1) Lorsque l'utilisateur clique sur le bouton _increase_ ou _decrease_ nous déclenchons un message `ChangeLevel` avec comme données attachées `playerId` et `howMuch`. 10 | 11 | (2) __Html.program__ (que `Navigation` encapsule) va en retour envoyer ce message à `Main.Update` qui va le diriger vers `Players.Update` (3). 12 | 13 | (4) `Players.Update` va retourner une commande pour sauvegarder le joueur, cette commande transite jusqu'à __Html.program__ (5). 14 | 15 | (6) Le runtime Elm exécute la commande (déclenche un appel d'API) et nous allons alors recevoir un résultat : une sauvegarde réussie ou un échec. Dans le cas d'une réussite, nous déclenchons un message `SaveSuccess` avec le joueur mis à jour en paramètre. 16 | 17 | (7) `Main.Update` redirige le message `SaveSuccess` vers `Players.Update`. 18 | 19 | (8) Dans `Players.Update` nous mettons à jour le modèle `players` et le retournons. Cela retourne ensuite dans Html.program. (9). 20 | 21 | (10) Alors, Html.program va afficher l'application avec le modèle mis à jour. 22 | -------------------------------------------------------------------------------- /fr/08-edition/01-plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/fr/08-edition/01-plan.png -------------------------------------------------------------------------------- /fr/08-edition/01-plan.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant Html.program as program #white 6 | participant Main.Update as MU #white 7 | participant Main.View as MV #white 8 | participant Players.Update as PU #white 9 | participant Players.Edit as PE #white 10 | 11 | PE -> program : PlayersMsg (ChangeLevel playerId howMuch) 12 | program -> MU : PlayersMsg (ChangeLevel playerId howMuch) 13 | MU -> PU : ChangeLevel playerId howMuch 14 | PU --> MU : Command to save 15 | MU --> program : Command to save 16 | ||| 17 | program -> MU : PlayersMsg (SaveSuccess player) 18 | MU -> PU : (SaveSuccess player) 19 | PU --> MU : Updated players 20 | MU --> program : Updated model 21 | program -> MV : Updated model 22 | 23 | 24 | @enduml 25 | 26 | -------------------------------------------------------------------------------- /fr/08-edition/02-messages.md: -------------------------------------------------------------------------------- 1 | > Cette page couvre Elm 0.18 2 | 3 | # Messages 4 | 5 | Commençons par ajouter les messages dont nous allons avoir besoin. 6 | 7 | Dans __src/Players/Messages.elm__ ajoutez : 8 | 9 | ```elm 10 | type Msg 11 | ... 12 | | ChangeLevel PlayerId Int 13 | | OnSave (Result Http.Error Player) 14 | ``` 15 | 16 | - `ChangeLevel` va être déclenché lorsque l'utilisateur veut changer le niveau. Le second paramètre est un entier indiquant de combien le niveau doit être changé : -1 pour diminuer ou 1 pour augmenter. 17 | - Ensuite nous allons envoyer une requête à l'API pour mettre à jour le joueur. `OnSave` sera déclenché une fois que la réponse de l'API aura été reçue. 18 | - `OnSave` contiendra, en cas de succès, le joueur mis à jour ou alors l'erreur Http en cas d'échec. 19 | -------------------------------------------------------------------------------- /fr/08-edition/03-edition-du-joueur.md: -------------------------------------------------------------------------------- 1 | > Cette page couvre Elm 0.18 2 | 3 | ## Vue d'édition du joueur 4 | 5 | Maintenant que nous avons créé un message `ChangeLevel`, déclenchons le à partir de la vue d'édition du joueur. 6 | 7 | Dans __src/Players/Edit.elm__ changez `btnLevelDecrease` et `btnLevelIncrease`: 8 | 9 | ```elm 10 | ... 11 | btnLevelDecrease : Player -> Html Msg 12 | btnLevelDecrease player = 13 | a [ class "btn ml1 h1", onClick (ChangeLevel player.id -1) ] 14 | [ i [ class "fa fa-minus-circle" ] [] ] 15 | 16 | 17 | btnLevelIncrease : Player -> Html Msg 18 | btnLevelIncrease player = 19 | a [ class "btn ml1 h1", onClick (ChangeLevel player.id 1) ] 20 | [ i [ class "fa fa-plus-circle" ] [] ] 21 | ``` 22 | 23 | Pour ces deux boutons nous avons ajouté `onClick (ChangeLevel player.id howMuch)`, où `howMuch` vaut `-1` pour diminuer de niveau et `1` pour augmenter. 24 | -------------------------------------------------------------------------------- /fr/08-edition/cover.md: -------------------------------------------------------------------------------- 1 | # Édition 2 | 3 | Dans le dernier chapitre de ce tutoriel nous allons éditer le niveau d'un joueur et le sauvegarder sur le serveur. 4 | 5 | À ce stade votre code devrait ressembler à ça : . 6 | -------------------------------------------------------------------------------- /fr/09-conclusion/cover.md: -------------------------------------------------------------------------------- 1 | # Conclusion 2 | 3 | Ce chapitre marque la fin de ce tutoriel, mais soyez sûr de le lire attentivement pour avoir quelques idées d'améliorations et de fonctionnalités supplémentaires. 4 | 5 | J'aimerais avoir vos retours pour améliorer ce tutoriel. N'hésitez pas à ouvrir des issues sur Github : . 6 | 7 | Merci ! 8 | -------------------------------------------------------------------------------- /fr/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/fr/logo.png -------------------------------------------------------------------------------- /fr/tips-tricks/context.md: -------------------------------------------------------------------------------- 1 | # Contextes 2 | 3 | Les fonctions `view` ou `update` ressemblent habituellement à ça : 4 | 5 | ```elm 6 | view : Model -> Html Msg 7 | view model = 8 | ... 9 | ``` 10 | 11 | Ou 12 | 13 | ```elm 14 | update : Msg -> Model -> (Model, Cmd Msg) 15 | update message model = 16 | ... 17 | ``` 18 | 19 | On pourrait facilement penser qu'on ne doit passer que le `Model` qui appartient à ce composant. Parfois, vous aurez besoin de plus d'informations, et il est absolument correct de la réclamer ! Par exemple : 20 | 21 | ```elm 22 | type alias Context = 23 | { model : Model 24 | , time : Time 25 | } 26 | 27 | view : Context -> Html Msg 28 | view context = 29 | ... 30 | ``` 31 | 32 | Cette fonction utilise le modèle du composant, mais aussi un objet `time` défini dans le modèle de son parent. 33 | -------------------------------------------------------------------------------- /fr/tips-tricks/troubleshooting.md: -------------------------------------------------------------------------------- 1 | # Résolution de problèmes 2 | 3 | Si le compilateur se comporte bizarrement pendant le développement, essayez d'effacer `elm-stuff/build-artifacts` et de compiler à nouveau : cela permet généralement de réparer plusieurs erreurs. -------------------------------------------------------------------------------- /helpers.md: -------------------------------------------------------------------------------- 1 | ➊ 2 | ➋ 3 | ➌ 4 | ➍ 5 | ➎ 6 | ➏ 7 | ➐ 8 | ➑ 9 | ➒ 10 | ➓ 11 | ✔ -------------------------------------------------------------------------------- /jp/01-foundations/01-hello.elm: -------------------------------------------------------------------------------- 1 | module Hello exposing (..) 2 | 3 | import Html exposing (text) 4 | 5 | 6 | main = 7 | text "Hello" 8 | -------------------------------------------------------------------------------- /jp/01-foundations/07-unit-type.md: -------------------------------------------------------------------------------- 1 | # ユニット型 2 | 3 | 空のタプル`()`はElmでは__ユニット型__と呼ばれます。一般的なので説明が必要でしょう。 4 | 5 | `a`で表される__型変数__を持つ型エイリアスを考えてみましょう: 6 | 7 | ```elm 8 | type alias Message a = 9 | { code : String 10 | , body : a 11 | } 12 | ``` 13 | 14 | このように `body`が`String`である`Message`を期待する関数を作ることができます: 15 | 16 | ```elm 17 | readMessage : Message String -> String 18 | readMessage message = 19 | ... 20 | ``` 21 | 22 | または `body`が整数のリストであるような`Message`を期待する関数も書けます: 23 | 24 | ```elm 25 | readMessage : Message (List Int) -> String 26 | readMessage message = 27 | ... 28 | ``` 29 | 30 | しかし、bodyに値を必要としない関数はどうでしょう?その場合、bodyが空であることを示すために、ユニット型を使用します。 31 | 32 | ```elm 33 | readMessage : Message () -> String 34 | readMessage message = 35 | ... 36 | ``` 37 | 38 | この関数は、__空のbody__を持つ `Message`をとります。これは__任意の値__ではなく、__空の値__と同じです。 39 | 40 | このように、ユニット型は通常、空の値の代わりとして使用されます。 41 | 42 | ## タスク 43 | 44 | `Task`型でのユニット型の使用例を見てみましょう。`Task`を使う場合、ユニット型を頻繁に使用します。 45 | 46 | 典型的なタスクは__エラー__と__結果__を持ちます。 47 | 48 | ```elm 49 | Task error result 50 | ``` 51 | 52 | - エラーを安全に無視できるタスクが必要な場合があります: `Task () result` 53 | - あるいは、結果を無視する場合: `Task error ()` 54 | - またはその両方を無視する場合: `Task () ()` 55 | -------------------------------------------------------------------------------- /jp/01-foundations/cover.md: -------------------------------------------------------------------------------- 1 | # 基礎 2 | 3 | この章の内容: 4 | 5 | - 基本的なElmアプリケーションの実行 6 | - Elmにおける関数と型の基礎 7 | -------------------------------------------------------------------------------- /jp/02-elm-arch/01-introduction.elm: -------------------------------------------------------------------------------- 1 | module App exposing (..) 2 | 3 | import Html exposing (Html, div, text, program) 4 | 5 | 6 | -- MODEL 7 | 8 | 9 | type alias Model = 10 | String 11 | 12 | 13 | init : ( Model, Cmd Msg ) 14 | init = 15 | ( "Hello", Cmd.none ) 16 | 17 | 18 | 19 | -- MESSAGES 20 | 21 | 22 | type Msg 23 | = NoOp 24 | 25 | 26 | 27 | -- VIEW 28 | 29 | 30 | view : Model -> Html Msg 31 | view model = 32 | div [] 33 | [ text model ] 34 | 35 | 36 | 37 | -- UPDATE 38 | 39 | 40 | update : Msg -> Model -> ( Model, Cmd Msg ) 41 | update msg model = 42 | case msg of 43 | NoOp -> 44 | ( model, Cmd.none ) 45 | 46 | 47 | 48 | -- SUBSCRIPTIONS 49 | 50 | 51 | subscriptions : Model -> Sub Msg 52 | subscriptions model = 53 | Sub.none 54 | 55 | 56 | 57 | -- MAIN 58 | 59 | 60 | main : Program Never Model Msg 61 | main = 62 | program 63 | { init = init 64 | , view = view 65 | , update = update 66 | , subscriptions = subscriptions 67 | } 68 | -------------------------------------------------------------------------------- /jp/02-elm-arch/04-flow.md: -------------------------------------------------------------------------------- 1 | >This page covers Elm 0.18 2 | 3 | # アプリケーションフロー 4 | 5 | 次の図は、アプリケーションの部分がHtml.programとどのように対話するかを示しています。 6 | 7 | ![Flow](04-flow.png) 8 | 9 | 1. `Html.program`は、初期モデルでビュー関数を呼び出してレンダリングします。 10 | 1. ユーザが「Expand」ボタンをクリックすると、ビューは「Expand」メッセージをトリガします。 11 | 1. `Html.program`は`Expand`メッセージを受け取り、`Expand`メッセージと現在のアプリケーション状態を受け取る`update`を呼び出します。 12 | 1. `update`関数は、更新された状態と実行するコマンド(または `Cmd.none`)を返すことによって、メッセージに反応します。 13 | 1. `Html.program`は更新された状態を受け取り、それを保存し、更新された状態を引数としてビューを呼び出します。 14 | 15 | 通常、 `Html.program`はElmアプリケーションが状態を保持する唯一の場所です。一つの大きな状態ツリーに集中しています。 16 | -------------------------------------------------------------------------------- /jp/02-elm-arch/04-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/jp/02-elm-arch/04-flow.png -------------------------------------------------------------------------------- /jp/02-elm-arch/04-flow.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber 3 | participant program #white 4 | participant update #white 5 | participant view #white 6 | 7 | program -> view : Render view 8 | ||| 9 | view -> program : Trigger message e.g. Expand 10 | program -> update : Send message with the current state 11 | update --> program : Return updated state and command 12 | program -> view : Render view 13 | @enduml 14 | -------------------------------------------------------------------------------- /jp/02-elm-arch/05-msg-payload.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (Html, button, div, text, program) 4 | import Html.Events exposing (onClick) 5 | 6 | 7 | -- MODEL 8 | 9 | 10 | type alias Model = 11 | Int 12 | 13 | 14 | init : ( Model, Cmd Msg ) 15 | init = 16 | ( 0, Cmd.none ) 17 | 18 | 19 | 20 | -- MESSAGES 21 | 22 | 23 | type Msg 24 | = Increment Int 25 | 26 | 27 | 28 | -- VIEW 29 | 30 | 31 | view : Model -> Html Msg 32 | view model = 33 | div [] 34 | [ button [ onClick (Increment 2) ] [ text "+" ] 35 | , text (toString model) 36 | ] 37 | 38 | 39 | 40 | -- UPDATE 41 | 42 | 43 | update : Msg -> Model -> ( Model, Cmd Msg ) 44 | update msg model = 45 | case msg of 46 | Increment howMuch -> 47 | ( model + howMuch, Cmd.none ) 48 | 49 | 50 | 51 | -- SUBSCRIPTIONS 52 | 53 | 54 | subscriptions : Model -> Sub Msg 55 | subscriptions model = 56 | Sub.none 57 | 58 | 59 | 60 | -- MAIN 61 | 62 | 63 | main : Program Never Model Msg 64 | main = 65 | program 66 | { init = init 67 | , view = view 68 | , update = update 69 | , subscriptions = subscriptions 70 | } 71 | -------------------------------------------------------------------------------- /jp/02-elm-arch/06-composing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/jp/02-elm-arch/06-composing.png -------------------------------------------------------------------------------- /jp/02-elm-arch/06-composing.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber "(#)" 3 | participant User #white 4 | participant program #white 5 | participant Main.initialModel as Mim #white 6 | participant Main.view as MV #white 7 | participant Main.update as MU #white 8 | participant Widget.initialModel as Wim #white 9 | participant Widget.view as WV #white 10 | participant Widget.update as WU #white 11 | 12 | program -> Mim: initialModel 13 | Mim -> Wim: initialModel 14 | Wim --> Mim: widgetModel 15 | Mim --> program: mainModel 16 | program -> MV : mainModel 17 | MV -> WV : widgetModel 18 | WV --> MV : Html 19 | MV --> program : Html 20 | program -> User : Html 21 | 22 | newpage 23 | 24 | autonumber 1 "(#)" 25 | User -> WV : Click 26 | WV -> MV: Increase 27 | MV -> program: (WidgetMsg Increase) 28 | program -> MU: (WidgetMsg Increase) mainModel 29 | MU -> WU : Increase widgetModel 30 | WU --> MU: (updated widgetModel, command) 31 | MU --> program: (updated mainModel, command) 32 | program -> MV : mainModel 33 | MV -> WV : widgetModel 34 | WV --> MV : Html 35 | MV --> program : Html 36 | @enduml 37 | -------------------------------------------------------------------------------- /jp/02-elm-arch/06-composing/Widget.elm: -------------------------------------------------------------------------------- 1 | module Widget exposing (..) 2 | 3 | import Html exposing (Html, button, div, text) 4 | import Html.Events exposing (onClick) 5 | 6 | 7 | -- MODEL 8 | 9 | 10 | type alias Model = 11 | { count : Int 12 | } 13 | 14 | 15 | initialModel : Model 16 | initialModel = 17 | { count = 0 18 | } 19 | 20 | 21 | type Msg 22 | = Increase 23 | 24 | 25 | 26 | -- VIEW 27 | 28 | 29 | view : Model -> Html Msg 30 | view model = 31 | div [] 32 | [ div [] [ text (toString model.count) ] 33 | , button [ onClick Increase ] [ Html.text "Click" ] 34 | ] 35 | 36 | 37 | 38 | -- UPDATE 39 | 40 | 41 | update : Msg -> Model -> ( Model, Cmd Msg ) 42 | update message model = 43 | case message of 44 | Increase -> 45 | ( { model | count = model.count + 1 }, Cmd.none ) 46 | -------------------------------------------------------------------------------- /jp/02-elm-arch/06-composing/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 | }, 14 | "elm-version": "0.18.0 <= v < 0.19.0" 15 | } -------------------------------------------------------------------------------- /jp/02-elm-arch/06-composing_001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/jp/02-elm-arch/06-composing_001.png -------------------------------------------------------------------------------- /jp/02-elm-arch/cover.md: -------------------------------------------------------------------------------- 1 | # Elmアーキテクチャ 2 | 3 | この章の内容: 4 | 5 | - Elmアーキテクチャ概要 6 | - Html.programの紹介 7 | - メッセージ 8 | - コマンド 9 | - サブスクリプション(購読) 10 | -------------------------------------------------------------------------------- /jp/03-subs-cmds/02-commands.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (Html, div, button, text, program) 4 | import Html.Events exposing (onClick) 5 | import Random 6 | 7 | 8 | -- MODEL 9 | 10 | 11 | type alias Model = 12 | Int 13 | 14 | 15 | init : ( Model, Cmd Msg ) 16 | init = 17 | ( 1, Cmd.none ) 18 | 19 | 20 | 21 | -- MESSAGES 22 | 23 | 24 | type Msg 25 | = Roll 26 | | OnResult Int 27 | 28 | 29 | 30 | -- VIEW 31 | 32 | 33 | view : Model -> Html Msg 34 | view model = 35 | div [] 36 | [ button [ onClick Roll ] [ text "Roll" ] 37 | , text (toString model) 38 | ] 39 | 40 | 41 | 42 | -- UPDATE 43 | 44 | 45 | update : Msg -> Model -> ( Model, Cmd Msg ) 46 | update msg model = 47 | case msg of 48 | Roll -> 49 | ( model, Random.generate OnResult (Random.int 1 6) ) 50 | 51 | OnResult res -> 52 | ( res, Cmd.none ) 53 | 54 | 55 | 56 | -- MAIN 57 | 58 | 59 | main : Program Never Model Msg 60 | main = 61 | program 62 | { init = init 63 | , view = view 64 | , update = update 65 | , subscriptions = (always Sub.none) 66 | } 67 | -------------------------------------------------------------------------------- /jp/03-subs-cmds/02-commands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/jp/03-subs-cmds/02-commands.png -------------------------------------------------------------------------------- /jp/03-subs-cmds/02-commands.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber "(#)" 3 | 4 | participant program #white 5 | participant Main.update as MU #white 6 | participant Child.update as CU #white 7 | participant GrandChild.update as GC #white 8 | 9 | program -> MU: update 10 | MU -> CU: update 11 | CU -> GC: update 12 | GC --> CU: (model, command) 13 | CU --> MU: (model, command) 14 | MU -> program : (model, command) 15 | 16 | @enduml 17 | -------------------------------------------------------------------------------- /jp/03-subs-cmds/cover.md: -------------------------------------------------------------------------------- 1 | # Subscriptions and Commands 2 | 3 | 外部入力を待ち受けて__副作用__を作成するために__サブスクリプション__、__コマンド__について学びます。 4 | 5 | この章の内容: 6 | 7 | - サブスクリプション(購読) 8 | - コマンド 9 | -------------------------------------------------------------------------------- /jp/04-starting/01-planning.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # 計画 4 | 5 | 私たちは、架空のロールプレイングゲームを追跡するための基本的なアプリケーションを構築します。 6 | 7 | ### リソース 8 | 9 | このガイドの残りの部分では、アプリケーションの対象となるモデル、たとえば、このアプリケーションでの__プレイヤー__などを__リソース__と呼びます。__モデル__という単語を使用すると、コンポーネント固有の状態もモデル(コンポーネントの展開/折りたたみ状態など)であるため、混乱する可能性があるためです。 10 | 11 | ## ワイヤーフレーム 12 | 13 | アプリケーションには2つのビューがあります: 14 | 15 | ![計画](01-planning.png) 16 | 17 | ### 画面➊ 18 | 19 | 選手のリストを表示します。この画面では次のことができます。 20 | 21 | - プレーヤーを編集するためにナビゲートする 22 | 23 | ### 画面➋ 24 | 25 | プレイヤーの編集ビューを表示します。この画面では次のことができます。 26 | 27 | - レベルを変更する 28 | 29 | これは非常に簡単なアプリケーションで、次のことをデモしています。 30 | 31 | - 複数のビュー 32 | - ネストされたコンポーネント 33 | - アプリケーションをリソースに分割する 34 | - ルーティング 35 | - アプリケーション全体の共有状態 36 | - レコードの操作の読み取りと編集 37 | - Ajaxリクエスト 38 | 39 | -------------------------------------------------------------------------------- /jp/04-starting/01-planning.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/jp/04-starting/01-planning.odg -------------------------------------------------------------------------------- /jp/04-starting/01-planning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/jp/04-starting/01-planning.png -------------------------------------------------------------------------------- /jp/04-starting/05-webpack-3.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Webpackその3 4 | 5 | ## 最初のElmアプリケーション 6 | 7 | 基本的なElmアプリケーションを作成します。 __src/Main.elm__では: 8 | 9 | ```elm 10 | module Main exposing (..) 11 | 12 | import Html exposing (Html, div, text, program) 13 | 14 | -- モデル 15 | 16 | 17 | type alias Model = 18 | String 19 | 20 | 21 | init : ( Model, Cmd Msg ) 22 | init = 23 | ( "Hello", Cmd.none ) 24 | 25 | 26 | 27 | -- メッセージ 28 | 29 | 30 | type Msg 31 | = NoOp 32 | 33 | 34 | 35 | -- ビュー 36 | 37 | 38 | view : Model -> Html Msg 39 | view model = 40 | div [] 41 | [ text model ] 42 | 43 | 44 | 45 | -- 更新 46 | 47 | 48 | update : Msg -> Model -> ( Model, Cmd Msg ) 49 | update msg model = 50 | case msg of 51 | NoOp -> 52 | ( model, Cmd.none ) 53 | 54 | 55 | 56 | -- サブスクリプション(購読) 57 | 58 | 59 | subscriptions : Model -> Sub Msg 60 | subscriptions model = 61 | Sub.none 62 | 63 | 64 | 65 | -- MAIN 66 | 67 | 68 | main : Program Never Model Msg 69 | main = 70 | program 71 | { init = init 72 | , view = view 73 | , update = update 74 | , subscriptions = subscriptions 75 | } 76 | ``` 77 | -------------------------------------------------------------------------------- /jp/04-starting/cover.md: -------------------------------------------------------------------------------- 1 | # アプリケーションの開始 2 | 3 | この章では、Elmアプリケーションの例を作成します。 4 | 5 | このチュートリアルでは、アプリケーションの構築に関する次の側面について説明します。 6 | 7 | - アプリケーションの構造 8 | - リソースの取得 9 | - ビュー 10 | - ルーティング 11 | - ユーザーの操作と変更の保存 12 | 13 | アプリケーションの詳細については、次のページを参照してください。 14 | -------------------------------------------------------------------------------- /jp/05-resources/01-intro.md: -------------------------------------------------------------------------------- 1 | # Playersリソース 2 | 3 | アプリケーション構造を、アプリケーションのリソース名で整理します。 このアプリでは、1つのリソース(`Players`)しか持たないので、`Players`ディレクトリしか存在しません。 4 | 5 | `Players`ディレクトリには、メインレベルのモジュールと同じように、Elmアーキテクチャのコンポーネントごとに1つのモジュールがあります。 6 | 7 | - Players/Messages.elm 8 | - Players/Models.elm 9 | - Players/Update.elm 10 | 11 | しかし、我々はプレイヤーのための異なるビューを持つことになります。リストビューと編集ビューです。 各ビューには独自のElmモジュールがあります。 12 | 13 | - Players/List.elm 14 | - Players/Edit.elm 15 | -------------------------------------------------------------------------------- /jp/05-resources/05-main-view.md: -------------------------------------------------------------------------------- 1 | >This page covers Elm 0.18 2 | 3 | # メインビュー 4 | 5 | __src/View.elm__を変更して、プレーヤーのリストを追加します: 6 | 7 | ```elm 8 | module View exposing (..) 9 | 10 | import Html exposing (Html, div, text) 11 | import Messages exposing (Msg(..)) 12 | import Models exposing (Model) 13 | import Players.List 14 | 15 | 16 | view : Model -> Html Msg 17 | view model = 18 | div [] 19 | [ page model ] 20 | 21 | 22 | page : Model -> Html Msg 23 | page model = 24 | Html.map PlayersMsg (Players.List.view model.players) 25 | ``` 26 | -------------------------------------------------------------------------------- /jp/05-resources/06-main.md: -------------------------------------------------------------------------------- 1 | >This page covers Elm 0.18 2 | 3 | # メイン 4 | 5 | 最後に`initialModel`を呼び出すように__src/Main.elm__を修正します: 6 | 7 | ```elm 8 | module Main exposing (..) 9 | 10 | import Html exposing (Html, div, text, program) 11 | import Messages exposing (Msg) 12 | import Models exposing (Model, initialModel) 13 | import Update exposing (update) 14 | import View exposing (view) 15 | 16 | init : ( Model, Cmd Msg ) 17 | init = 18 | ( initialModel, Cmd.none ) 19 | 20 | subscriptions : Model -> Sub Msg 21 | subscriptions model = 22 | Sub.none 23 | 24 | -- MAIN 25 | 26 | main = 27 | program 28 | { init = init 29 | , view = view 30 | , update = update 31 | , subscriptions = subscriptions 32 | } 33 | ``` 34 | 35 | ここでは、インポートに `initialModel`を追加し、`init`を追加しました。 36 | 37 | --- 38 | 39 | アプリケーションを実行すると、1人のユーザーのリストが表示されます。 40 | 41 | ![Screenshot](screenshot.png) 42 | 43 | アプリケーションはのようになります。 44 | -------------------------------------------------------------------------------- /jp/05-resources/cover.md: -------------------------------------------------------------------------------- 1 | # リソース 2 | 3 | これまでのコードはのようになります。 4 | 5 | この章では、最初のリソースPlayersをアプリケーションに追加します。 6 | -------------------------------------------------------------------------------- /jp/05-resources/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/jp/05-resources/screenshot.png -------------------------------------------------------------------------------- /jp/06-fetching-resources/01-plan.md: -------------------------------------------------------------------------------- 1 | # 計画 2 | 3 | 次のステップは、前に作成した偽のAPIからプレーヤのリストを取得することです。 4 | 5 | これは計画です: 6 | 7 | ![計画](01-plan.png) 8 | 9 | (1-2)アプリケーションがロードされると、Httpリクエストを開始してプレイヤーを取得するコマンドを起動します。 これはHtml.programの `init`で行われます。 10 | 11 | (3-6)リクエストが完了すると、データとともに「FetchAllDone」をトリガーします。このメッセージはプレーヤーのコレクションを更新する `Players.Update`に流れます。 12 | 13 | (7-10)その後、アプリケーションは更新されたプレーヤーのリストをレンダリングします。 14 | 15 | ## 依存関係 16 | 17 | `http`モジュールが必要なのでインストールしておきます: 18 | 19 | ```bash 20 | elm package install elm-lang/http 21 | ``` 22 | -------------------------------------------------------------------------------- /jp/06-fetching-resources/01-plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/jp/06-fetching-resources/01-plan.png -------------------------------------------------------------------------------- /jp/06-fetching-resources/01-plan.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant program #white 6 | participant init #white 7 | participant Main.Update as MU #white 8 | participant Main.View as MV #white 9 | participant Players.Update as PU #white 10 | participant Players.List as PL #white 11 | 12 | program -> init 13 | init --> program : fetchAll 14 | program -> MU : (model, PlayersMsg (FetchAllDone players)) 15 | MU -> PU : (currentPlayers, FetchAllDone players) 16 | PU --> MU : Updated players' collection 17 | MU --> program : Updated app model 18 | program -> MV : App model 19 | MV -> PL : Players 20 | PL --> MV :Rendered view 21 | MV --> program : Rendered view 22 | @enduml 23 | -------------------------------------------------------------------------------- /jp/06-fetching-resources/02-players-messages.md: -------------------------------------------------------------------------------- 1 | >This page covers Elm 0.18 2 | 3 | # Playersメッセージ 4 | 5 | まず、プレイヤーを取得するために必要なメッセージを作成しましょう。__src/Players/Messages.elm__に新しいインポートとメッセージを追加します。 6 | 7 | ```elm 8 | module Players.Messages exposing (..) 9 | 10 | import Http 11 | import Players.Models exposing (PlayerId, Player) 12 | 13 | 14 | type Msg 15 | = OnFetchAll (Result Http.Error (List Player)) 16 | ``` 17 | 18 | `OnFetchAll`はサーバからの応答を取得するときに呼び出されます。このメッセージは`Http.Error`かフェッチされたプレイヤーのリストのいずれかになる` Result`を保持します。 19 | -------------------------------------------------------------------------------- /jp/06-fetching-resources/03-players-update.md: -------------------------------------------------------------------------------- 1 | >This page covers Elm 0.18 2 | 3 | # プレーヤーの更新 4 | 5 | プレーヤーのリクエストが完了すると、 `OnFetchAll`メッセージがトリガーされます。 6 | 7 | __src/Players/Update.elm__は、この新しいメッセージに責任を持つ必要があります。 `update`を以下のように変更してください: 8 | 9 | ```elm 10 | ... 11 | update : Msg -> List Player -> ( List Player, Cmd Msg ) 12 | update message players = 13 | case message of 14 | OnFetchAll (Ok newPlayers) -> 15 | ( newPlayers, Cmd.none ) 16 | 17 | OnFetchAll (Err error) -> 18 | ( players, Cmd.none ) 19 | ``` 20 | 21 | `OnFetchAll`というメッセージを得たとき、何を実行するかを決定するためにパターンマッチングを使用できます。 22 | 23 | - `Ok`の場合、取得されたプレーヤーを返して、プレーヤーのコレクションを更新します。 24 | - `Err`の場合、私たちは今までに持っていたものを返すだけです(もっと良いのはユーザーにエラーを表示することですが、チュートリアルを簡単にするために省略します)。 25 | -------------------------------------------------------------------------------- /jp/06-fetching-resources/05-main.md: -------------------------------------------------------------------------------- 1 | >This page covers Elm 0.18 2 | 3 | # メイン 4 | 5 | ## メインのモデル 6 | 7 | __src/Models.elm__のハードコーディングされたプレイヤーのリストを削除します。 8 | 9 | ```elm 10 | initialModel : Model 11 | initialModel = 12 | { players = [] 13 | } 14 | ``` 15 | 16 | ## メイン 17 | 18 | 最後に、アプリケーションを起動するときに `fetchAll`を実行します。 19 | 20 | __src/Main.elm__を以下のように修正します: 21 | 22 | ```elm 23 | ... 24 | import Messages exposing (Msg(..)) 25 | ... 26 | import Players.Commands exposing (fetchAll) 27 | 28 | init : ( Model, Cmd Msg ) 29 | init = 30 | ( initialModel, Cmd.map PlayersMsg fetchAll ) 31 | ``` 32 | 33 | これで `init`はアプリケーションの起動時に実行するコマンドのリストを返します。 34 | -------------------------------------------------------------------------------- /jp/06-fetching-resources/06-try-it.md: -------------------------------------------------------------------------------- 1 | >This page covers Elm 0.18 2 | 3 | # 試してみよう 4 | 5 | さあ試してみましょう! ある端末でアプリケーションを実行するには: 6 | 7 | ```bash 8 | nf start 9 | ``` 10 | 11 | ブラウザをリフレッシュすると、アプリケーションはサーバーからプレーヤーのリストを取得するようになりました。 アプリは次のようになります: 12 | 13 | ![Screenshot](screenshot.png) 14 | 15 | アプリケーションコードはのようにこの段階を見なければなりません。 16 | -------------------------------------------------------------------------------- /jp/06-fetching-resources/cover.md: -------------------------------------------------------------------------------- 1 | # リソースの取得 2 | 3 | この章では、偽のAPIからプレーヤーのコレクションを取得する方法について説明します。 4 | 5 | これまでのアプリケーションコードは、のようになります。 6 | -------------------------------------------------------------------------------- /jp/06-fetching-resources/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/jp/06-fetching-resources/screenshot.png -------------------------------------------------------------------------------- /jp/07-routing/01-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/jp/07-routing/01-intro.png -------------------------------------------------------------------------------- /jp/07-routing/01-intro.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant Browser #white 6 | participant Navigation #white 7 | participant init #white 8 | participant update #white 9 | participant parseLocation #white 10 | participant View #white 11 | 12 | Navigation -> init : Current location 13 | init -> parseLocation : Location 14 | parseLocation --> init : Matched Route 15 | init --> Navigation : Initial model 16 | Navigation -> View : Model 17 | View --> Navigation : Rendered view 18 | 19 | newpage 20 | 21 | autonumber 1 "(#)" 22 | Browser -> Navigation : Location change event 23 | Navigation -> update : OnLocationChange 24 | update -> parseLocation : Location 25 | parseLocation --> update : Matched Route 26 | update --> Navigation : Updated model 27 | Navigation -> View : Model 28 | View --> Navigation : Rendered view 29 | 30 | @enduml 31 | 32 | -------------------------------------------------------------------------------- /jp/07-routing/01-intro_001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/jp/07-routing/01-intro_001.png -------------------------------------------------------------------------------- /jp/07-routing/04-main-model.md: -------------------------------------------------------------------------------- 1 | >This page covers Elm 0.18 2 | 3 | # メインモデル 4 | 5 | 私たちのメインのアプリケーションモデルでは、現在のルートを保存します。 6 | __src/Models.elm__を次のように変更します。 7 | 8 | ```elm 9 | module Models exposing (..) 10 | 11 | import Players.Models exposing (Player) 12 | import Routing 13 | 14 | 15 | type alias Model = 16 | { players : List Player 17 | , route : Routing.Route 18 | } 19 | 20 | 21 | initialModel : Routing.Route -> Model 22 | initialModel route = 23 | { players = [] 24 | , route = route 25 | } 26 | ``` 27 | 28 | ここで我々は: 29 | 30 | - モデルに `route`を追加しました 31 | - `initialModel`を、引数`route`を取るように変更しました 32 | -------------------------------------------------------------------------------- /jp/07-routing/05-main-messages.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # メインメッセージ 4 | 5 | ブラウザ閲覧ロケーションが変更されたとき、新しいメッセージがトリガーされます。 6 | 7 | __src/Messages.elm__を以下のように変更してください: 8 | 9 | ```elm 10 | module Messages exposing (..) 11 | 12 | import Navigation exposing (Location) 13 | import Players.Messages 14 | 15 | 16 | type Msg 17 | = PlayersMsg Players.Messages.Msg 18 | | OnLocationChange Location 19 | ``` 20 | 21 | - `Navigation`をインポートする 22 | - `OnLocationChange Location`メッセージを追加する 23 | -------------------------------------------------------------------------------- /jp/07-routing/06-main-update.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | 4 | # メインアップデート 5 | 6 | 新規の`OnLocationChange`メッセージを処理するMainの`update`関数です。 7 | 8 | __src/Update.elm__に新しい分岐の枝を追加します: 9 | 10 | ```elm 11 | ... 12 | import Routing exposing (parseLocation) 13 | 14 | ... 15 | 16 | update msg model = 17 | case msg of 18 | ... 19 | OnLocationChange location -> 20 | let 21 | newRoute = 22 | parseLocation location 23 | in 24 | ( { model | route = newRoute }, Cmd.none ) 25 | ``` 26 | 27 | ここで、`OnLocationChange`メッセージを受け取ると、このlocationをパースし、一致したルートをモデルに格納します。 28 | -------------------------------------------------------------------------------- /jp/07-routing/09-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/jp/07-routing/09-edit.png -------------------------------------------------------------------------------- /jp/07-routing/09-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/jp/07-routing/09-list.png -------------------------------------------------------------------------------- /jp/07-routing/09-try-it.md: -------------------------------------------------------------------------------- 1 | # 試してみよう 2 | 3 | これまでのことを試してみましょう。 次のようにしてアプリケーションを実行します。 4 | 5 | ```bash 6 | nf start 7 | ``` 8 | 9 | ブラウザで `http://localhost:3000`に行きます。 ユーザーの一覧が表示されます。 10 | 11 | ![screenshot](09-list.png) 12 | 13 | `http://localhost:3000/#players/2`に行くと、1人のユーザーが表示されます。 14 | 15 | ![screenshot](09-edit.png) 16 | 17 | 次に、ナビゲーションを追加します。 18 | 19 | この時点までに、アプリケーションコードはになります。 20 | -------------------------------------------------------------------------------- /jp/07-routing/cover.md: -------------------------------------------------------------------------------- 1 | # ルーティング 2 | 3 | この章では、アプリケーションへのルーティングの追加について説明します。 4 | 5 | これまでのアプリケーションコードは、のようになります。 6 | -------------------------------------------------------------------------------- /jp/08-edit/01-plan.md: -------------------------------------------------------------------------------- 1 | # 計画 2 | 3 | プレーヤーのレベルを変更する計画は次のとおりです。 4 | 5 | ![Flow](01-plan.png) 6 | 7 | (1) ユーザーが増加、減少のボタンをクリックすると、 `playerId`と`howMuch`をペイロードとして、 `ChangeLevel`メッセージをトリガーします。 8 | 9 | (2) __Html.program__(ナビゲーションがラップしている)は、このメッセージを `Main.Update`に送り返し、`Players.Update`(3)に送ります。 10 | 11 | (4) `Players.Update`はプレーヤーを保存するコマンドを返します。このコマンドは__Html.program__(5)に流れます。 12 | 13 | (6) Elmランタイムはコマンドを実行し(API呼び出しをトリガする)、保存成功または失敗のいずれかの結果を返します。 成功の場合、更新されたプレーヤーをペイロードとして「SaveSuccess」メッセージをトリガーします。 14 | 15 | (7) `Main.Update`は`SaveSuccess`メッセージを `Players.Update`にルーティングします。 16 | 17 | (8) `Players.Update`では`players`モデルを更新して返します。 これはHtml.program(9)に戻ります。 18 | 19 | (10) その後、Html.programは更新されたモデルでアプリケーションをレンダリングします。 20 | -------------------------------------------------------------------------------- /jp/08-edit/01-plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/jp/08-edit/01-plan.png -------------------------------------------------------------------------------- /jp/08-edit/01-plan.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant Html.program as program #white 6 | participant Main.Update as MU #white 7 | participant Main.View as MV #white 8 | participant Players.Update as PU #white 9 | participant Players.Edit as PE #white 10 | 11 | PE -> program : PlayersMsg (ChangeLevel playerId howMuch) 12 | program -> MU : PlayersMsg (ChangeLevel playerId howMuch) 13 | MU -> PU : ChangeLevel playerId howMuch 14 | PU --> MU : Command to save 15 | MU --> program : Command to save 16 | ||| 17 | program -> MU : PlayersMsg (SaveSuccess player) 18 | MU -> PU : (SaveSuccess player) 19 | PU --> MU : Updated players 20 | MU --> program : Updated model 21 | program -> MV : Updated model 22 | 23 | 24 | @enduml 25 | 26 | -------------------------------------------------------------------------------- /jp/08-edit/02-messages.md: -------------------------------------------------------------------------------- 1 | # メッセージ 2 | 3 | まず、必要なメッセージを追加してみましょう。 4 | 5 | __src/Players/Messages.elm__に以下を追加: 6 | 7 | ```elm 8 | type Msg 9 | ... 10 | | ChangeLevel PlayerId Int 11 | | OnSave (Result Http.Error Player) 12 | ``` 13 | 14 | - ユーザーがレベルを変更したいときに `ChangeLevel`がトリガーされます。第2のパラメータは、レベルをどれだけ変化させるかを示す整数です。減少する場合は-1、増加する場合は1になります。 15 | - その後、プレーヤーをAPIに更新するようリクエストします。 `OnSave`はAPIからの成功した応答の後にトリガされます。 16 | - `OnSave`は成功時には更新されたプレイヤーを運び、失敗時にはHttpエラーを運びます。 17 | -------------------------------------------------------------------------------- /jp/08-edit/03-player-edit.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | ## プレイヤー編集ビュー 4 | 5 | 私たちは `ChangeLevel`メッセージを作成しました。 このメッセージをプレイヤーの編集ビューからトリガーしましょう。 6 | 7 | __src/Players/Edit.elm__で `btnLevelDecrease`と`btnLevelIncrease`を変更してください: 8 | 9 | ```elm 10 | ... 11 | btnLevelDecrease : Player -> Html Msg 12 | btnLevelDecrease player = 13 | a [ class "btn ml1 h1", onClick (ChangeLevel player.id -1) ] 14 | [ i [ class "fa fa-minus-circle" ] [] ] 15 | 16 | 17 | btnLevelIncrease : Player -> Html Msg 18 | btnLevelIncrease player = 19 | a [ class "btn ml1 h1", onClick (ChangeLevel player.id 1) ] 20 | [ i [ class "fa fa-plus-circle" ] [] ] 21 | ``` 22 | 23 | これらの2つのボタンに`onClick(ChangeLevel player.id howMuch)`を追加しました。ここで`howMuch`はレベルを下げる場合は`-1`、レベルを下げ場合には`1`になります。 24 | -------------------------------------------------------------------------------- /jp/08-edit/cover.md: -------------------------------------------------------------------------------- 1 | # 編集 2 | 3 | このチュートリアルの最後の章では、プレイヤーのレベルを編集してバックエンドに保存します。 4 | 5 | この時点までのアプリケーションコードはのようになります。 6 | -------------------------------------------------------------------------------- /jp/09-conclusion/01-improvements.md: -------------------------------------------------------------------------------- 1 | # さらなる改善 2 | 3 | このアプリを、以下のように改善していくことができます。 4 | 5 | ## プレーヤーの作成と削除 6 | 7 | チュートリアルを短くするために実施していませんが、間違いなく重要な機能です。 8 | 9 | ## プレーヤーの名前を変更する 10 | 11 | ## Httpリクエストが失敗したときにエラーメッセージを表示する 12 | 13 | プレイヤーの獲得や保存が失敗した場合、私たちは何もしません。ユーザーにエラーメッセージを表示するとよいでしょう。 14 | 15 | ## さらに良いエラーメッセージ 16 | 17 | エラーメッセージを表示するだけでなく、 18 | 19 | - エラーや情報などの、さまざまな種類のフラッシュメッセージを表示する。 20 | - 複数のフラッシュメッセージを同時に表示する 21 | - メッセージを却下する能力がある 22 | - 数秒後に自動的にメッセージを削除する 23 | 24 | ## 楽観的な更新 25 | 26 | 現時点では、すべての更新機能は悲観的です。つまり、サーバーからの応答が成功するまでモデルを変更しないということです。大きな改善案としては、楽観的な作成・更新・削除を追加することです。しかし、これを可能とするためには、より良いエラー処理が必要になります。 27 | 28 | ## バリデーション 29 | 30 | 名前のないプレイヤーは避けるべきでしょう。プレーヤーの名前を検証し、空にできないようにするのが良いでしょう。 31 | 32 | ## アイテムとボーナスを追加 33 | 34 | プレーヤーがアイテムのリストを持てるようにすることができます。これらのアイテムは、機器、衣類、巻物、アクセサリー、たとえば「鋼鉄の剣」などです。それから、プレイヤーと特典の間には関連を持たせます。 35 | 36 | それぞれの特典にはボーナスが付いています。プレイヤーは計算された強さに、レベルとボーナスを加えた合計を計算します。 37 | 38 | --- 39 | 40 | このアプリケーションのより機能的なバージョンについては、のマスターブランチを参照してください。 41 | -------------------------------------------------------------------------------- /jp/09-conclusion/cover.md: -------------------------------------------------------------------------------- 1 | # おわりに 2 | 3 | 以上でこのチュートリアルは終了しますが、改善や機能に関するアイデアをお読みください。 4 | 5 | 私はこのチュートリアルを改善するためにあなたのフィードバックをお聞きしたいと思います。 でissueを開いてください。 6 | 7 | ありがとう! 8 | -------------------------------------------------------------------------------- /jp/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/jp/logo.png -------------------------------------------------------------------------------- /jp/tips-tricks/context.md: -------------------------------------------------------------------------------- 1 | # コンテキスト 2 | 3 | 典型的な `update`や` view`関数は次のようになります: 4 | 5 | ```elm 6 | view : Model -> Html Msg 7 | view model = 8 | ... 9 | ``` 10 | 11 | あるいは 12 | 13 | ```elm 14 | update : Msg -> Model -> (Model, Cmd Msg) 15 | update message model = 16 | ... 17 | ``` 18 | 19 | このコンポーネントの`Model`だけを渡すということで非常にシンプルな話です。しかし、余分な情報が必要なとき、viewに追加的な情報を渡すのも問題ありません。例えば: 20 | 21 | ```elm 22 | type alias Context = 23 | { model : Model 24 | , time : Time 25 | } 26 | 27 | view : Context -> Html Msg 28 | view context = 29 | ... 30 | ``` 31 | 32 | この関数は、親モデルで定義されているコンポーネントモデルと`time`を必要としています。 33 | 34 | -------------------------------------------------------------------------------- /jp/tips-tricks/troubleshooting.md: -------------------------------------------------------------------------------- 1 | # トラブルシューティング 2 | 3 | 開発中に奇妙なコンパイラの動作が見つかった場合、`elm-stuff/build-artifacts`を削除してもう一度コンパイルすると、問題が修正される場合があります。 4 | -------------------------------------------------------------------------------- /ko/01-foundations/01-hello.elm: -------------------------------------------------------------------------------- 1 | module Hello exposing (..) 2 | 3 | import Html exposing (text) 4 | 5 | 6 | main = 7 | text "Hello" 8 | -------------------------------------------------------------------------------- /ko/01-foundations/07-unit-type.md: -------------------------------------------------------------------------------- 1 | # 유닛 타입 2 | 3 | 빈 튜플 `()` 은 Elm 에서 __유닛 타입__ 이라 부릅니다. 이는 설명이 조금 필요합니다. 4 | 5 | __타입 변수__ (`a` 로 표현되는) 를 가진 타입 앨리어스가 있습니다: 6 | 7 | ```elm 8 | type alias Message a = 9 | { code : String 10 | , body : a 11 | } 12 | ``` 13 | 14 | `body` 를 `String` 으로 갖는 `Message` 는 이렇게 만듭니다: 15 | 16 | ```elm 17 | readMessage : Message String -> String 18 | readMessage message = 19 | ... 20 | ``` 21 | 22 | `body` 를 정수 (Int) 의 리스트 (List) 로 가지려면 이렇게 만들면 됩니다: 23 | 24 | ```elm 25 | readMessage : Message (List Int) -> String 26 | readMessage message = 27 | ... 28 | ``` 29 | 30 | body 의 값이 필요하지 않은 경우는 어떨까요? body 가 어떤 값도 아니라는 뜻으로 유닛 타입을 사용합니다: 31 | 32 | ```elm 33 | readMessage : Message () -> String 34 | readMessage message = 35 | ... 36 | ``` 37 | 38 | 이 함수는 __빈 body__ 를 가진 `Message` 입니다. __아무 값__ 이 아니라, __비어있는__ 겁니다. 39 | 40 | 따라서 빈 값을 표현하는 데 유닛 타입이 흔히 사용된다고 볼 수 있습니다. 41 | 42 | ## Task 타입 43 | 44 | 하나의 실전 예시는 `Task` 타입입니다. 여러분이 `Task` 를 쓰게 되면, 유닛 타입을 정말 자주 보게 될겁니다. 45 | 46 | 보통 Task 는 __error__ 와 __result__ 를 가집니다: 47 | 48 | ```elm 49 | Task error result 50 | ``` 51 | 52 | - 가끔은 에러가 무시되어도 상관없는 경우가 있죠: `Task () result` 53 | - 아니면 결과를 무시하거나: `Task error ()` 54 | - 둘 다일때도 있습니다: `Task () ()` 55 | -------------------------------------------------------------------------------- /ko/01-foundations/cover.md: -------------------------------------------------------------------------------- 1 | # 기초 2 | 3 | 이 챕터에서는 아래 내용을 다룹니다: 4 | 5 | - 기본적인 Elm 어플리케이션 구동 6 | - Elm 의 함수와 타입 기초 7 | -------------------------------------------------------------------------------- /ko/02-elm-arch/01-introduction.elm: -------------------------------------------------------------------------------- 1 | module App exposing (..) 2 | 3 | import Html exposing (Html, div, text, program) 4 | 5 | 6 | -- MODEL 7 | 8 | 9 | type alias Model = 10 | String 11 | 12 | 13 | init : ( Model, Cmd Msg ) 14 | init = 15 | ( "Hello", Cmd.none ) 16 | 17 | 18 | 19 | -- MESSAGES 20 | 21 | 22 | type Msg 23 | = NoOp 24 | 25 | 26 | 27 | -- VIEW 28 | 29 | 30 | view : Model -> Html Msg 31 | view model = 32 | div [] 33 | [ text model ] 34 | 35 | 36 | 37 | -- UPDATE 38 | 39 | 40 | update : Msg -> Model -> ( Model, Cmd Msg ) 41 | update msg model = 42 | case msg of 43 | NoOp -> 44 | ( model, Cmd.none ) 45 | 46 | 47 | 48 | -- SUBSCRIPTIONS 49 | 50 | 51 | subscriptions : Model -> Sub Msg 52 | subscriptions model = 53 | Sub.none 54 | 55 | 56 | 57 | -- MAIN 58 | 59 | 60 | main : Program Never Model Msg 61 | main = 62 | program 63 | { init = init 64 | , view = view 65 | , update = update 66 | , subscriptions = subscriptions 67 | } 68 | -------------------------------------------------------------------------------- /ko/02-elm-arch/04-flow.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # 어플리케이션 흐름 4 | 5 | 아래 다이어그램은 앱의 각 부분들이 Html.program 과 어떻게 작용하는지 보여줍니다. 6 | 7 | ![Flow](04-flow.png) 8 | 9 | 1. `Html.program` 은 뷰 함수를 초기 상태로 호출하여 처음 화면을 그린다. 10 | 1. 사용자가 Expand 버튼을 누르면, 뷰는 `Expand` 메시지를 보낸다. 11 | 1. `Html.program` 은 `Expand` 메시지를 받고 `update` 함수에 `Expand` 메시지와 현재 상태를 전달하여 호출한다. 12 | 1. update 함수는 메시지를 처리해 갱신된 상태와 실행할 커맨드를 리턴한다. (혹은 `Cmd.none`) 13 | 1. `Html.program` 는 갱신된 상태 (state) 를 받아 저장하고, view 에 전달하여 호출한다. 14 | 15 | 일반적으로는 `Html.program` 이 Elm 어플리케이션의 단일화된 트리 구조의 상태를 관리하는 유일한 곳이라고 할 수 있습니다. 16 | -------------------------------------------------------------------------------- /ko/02-elm-arch/04-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/ko/02-elm-arch/04-flow.png -------------------------------------------------------------------------------- /ko/02-elm-arch/04-flow.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber 3 | participant program #white 4 | participant update #white 5 | participant view #white 6 | 7 | program -> view : Render view 8 | ||| 9 | view -> program : Trigger message e.g. Expand 10 | program -> update : Send message with the current state 11 | update --> program : Return updated state and command 12 | program -> view : Render view 13 | @enduml 14 | -------------------------------------------------------------------------------- /ko/02-elm-arch/05-msg-payload.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (Html, button, div, text, program) 4 | import Html.Events exposing (onClick) 5 | 6 | 7 | -- MODEL 8 | 9 | 10 | type alias Model = 11 | Int 12 | 13 | 14 | init : ( Model, Cmd Msg ) 15 | init = 16 | ( 0, Cmd.none ) 17 | 18 | 19 | 20 | -- MESSAGES 21 | 22 | 23 | type Msg 24 | = Increment Int 25 | 26 | 27 | 28 | -- VIEW 29 | 30 | 31 | view : Model -> Html Msg 32 | view model = 33 | div [] 34 | [ button [ onClick (Increment 2) ] [ text "+" ] 35 | , text (toString model) 36 | ] 37 | 38 | 39 | 40 | -- UPDATE 41 | 42 | 43 | update : Msg -> Model -> ( Model, Cmd Msg ) 44 | update msg model = 45 | case msg of 46 | Increment howMuch -> 47 | ( model + howMuch, Cmd.none ) 48 | 49 | 50 | 51 | -- SUBSCRIPTIONS 52 | 53 | 54 | subscriptions : Model -> Sub Msg 55 | subscriptions model = 56 | Sub.none 57 | 58 | 59 | 60 | -- MAIN 61 | 62 | 63 | main : Program Never Model Msg 64 | main = 65 | program 66 | { init = init 67 | , view = view 68 | , update = update 69 | , subscriptions = subscriptions 70 | } 71 | -------------------------------------------------------------------------------- /ko/02-elm-arch/06-composing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/ko/02-elm-arch/06-composing.png -------------------------------------------------------------------------------- /ko/02-elm-arch/06-composing.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber "(#)" 3 | participant User #white 4 | participant program #white 5 | participant Main.initialModel as Mim #white 6 | participant Main.view as MV #white 7 | participant Main.update as MU #white 8 | participant Widget.initialModel as Wim #white 9 | participant Widget.view as WV #white 10 | participant Widget.update as WU #white 11 | 12 | program -> Mim: initialModel 13 | Mim -> Wim: initialModel 14 | Wim --> Mim: widgetModel 15 | Mim --> program: mainModel 16 | program -> MV : mainModel 17 | MV -> WV : widgetModel 18 | WV --> MV : Html 19 | MV --> program : Html 20 | program -> User : Html 21 | 22 | newpage 23 | 24 | autonumber 1 "(#)" 25 | User -> WV : Click 26 | WV -> MV: Increase 27 | MV -> program: (WidgetMsg Increase) 28 | program -> MU: (WidgetMsg Increase) mainModel 29 | MU -> WU : Increase widgetModel 30 | WU --> MU: (updated widgetModel, command) 31 | MU --> program: (updated mainModel, command) 32 | program -> MV : mainModel 33 | MV -> WV : widgetModel 34 | WV --> MV : Html 35 | MV --> program : Html 36 | @enduml 37 | -------------------------------------------------------------------------------- /ko/02-elm-arch/06-composing/Widget.elm: -------------------------------------------------------------------------------- 1 | module Widget exposing (..) 2 | 3 | import Html exposing (Html, button, div, text) 4 | import Html.Events exposing (onClick) 5 | 6 | 7 | -- MODEL 8 | 9 | 10 | type alias Model = 11 | { count : Int 12 | } 13 | 14 | 15 | initialModel : Model 16 | initialModel = 17 | { count = 0 18 | } 19 | 20 | 21 | type Msg 22 | = Increase 23 | 24 | 25 | 26 | -- VIEW 27 | 28 | 29 | view : Model -> Html Msg 30 | view model = 31 | div [] 32 | [ div [] [ text (toString model.count) ] 33 | , button [ onClick Increase ] [ Html.text "Click" ] 34 | ] 35 | 36 | 37 | 38 | -- UPDATE 39 | 40 | 41 | update : Msg -> Model -> ( Model, Cmd Msg ) 42 | update message model = 43 | case message of 44 | Increase -> 45 | ( { model | count = model.count + 1 }, Cmd.none ) 46 | -------------------------------------------------------------------------------- /ko/02-elm-arch/06-composing/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 | }, 14 | "elm-version": "0.18.0 <= v < 0.19.0" 15 | } -------------------------------------------------------------------------------- /ko/02-elm-arch/06-composing_001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/ko/02-elm-arch/06-composing_001.png -------------------------------------------------------------------------------- /ko/02-elm-arch/cover.md: -------------------------------------------------------------------------------- 1 | # Elm 아키텍쳐 2 | 3 | 이 챕터에서 다루는 것들: 4 | 5 | - Elm 아키텍쳐 전반 6 | - Html.program 7 | - 메시지 8 | - 커맨드 9 | - 서브스크립션 10 | -------------------------------------------------------------------------------- /ko/03-subs-cmds/02-commands.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (Html, div, button, text, program) 4 | import Html.Events exposing (onClick) 5 | import Random 6 | 7 | 8 | -- MODEL 9 | 10 | 11 | type alias Model = 12 | Int 13 | 14 | 15 | init : ( Model, Cmd Msg ) 16 | init = 17 | ( 1, Cmd.none ) 18 | 19 | 20 | 21 | -- MESSAGES 22 | 23 | 24 | type Msg 25 | = Roll 26 | | OnResult Int 27 | 28 | 29 | 30 | -- VIEW 31 | 32 | 33 | view : Model -> Html Msg 34 | view model = 35 | div [] 36 | [ button [ onClick Roll ] [ text "Roll" ] 37 | , text (toString model) 38 | ] 39 | 40 | 41 | 42 | -- UPDATE 43 | 44 | 45 | update : Msg -> Model -> ( Model, Cmd Msg ) 46 | update msg model = 47 | case msg of 48 | Roll -> 49 | ( model, Random.generate OnResult (Random.int 1 6) ) 50 | 51 | OnResult res -> 52 | ( res, Cmd.none ) 53 | 54 | 55 | 56 | -- MAIN 57 | 58 | 59 | main : Program Never Model Msg 60 | main = 61 | program 62 | { init = init 63 | , view = view 64 | , update = update 65 | , subscriptions = (always Sub.none) 66 | } 67 | -------------------------------------------------------------------------------- /ko/03-subs-cmds/02-commands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/ko/03-subs-cmds/02-commands.png -------------------------------------------------------------------------------- /ko/03-subs-cmds/02-commands.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber "(#)" 3 | 4 | participant program #white 5 | participant Main.update as MU #white 6 | participant Child.update as CU #white 7 | participant GrandChild.update as GC #white 8 | 9 | program -> MU: update 10 | MU -> CU: update 11 | CU -> GC: update 12 | GC --> CU: (model, command) 13 | CU --> MU: (model, command) 14 | MU -> program : (model, command) 15 | 16 | @enduml 17 | -------------------------------------------------------------------------------- /ko/03-subs-cmds/cover.md: -------------------------------------------------------------------------------- 1 | # 서브스크립션과 커맨드 2 | 3 | 외부 입력과 __사이드 이펙트__ 를 처리하기 위해서는 __서브스크립션__ 과 __커맨드__ 에 대해 알아둘 필요가 있습니다. 4 | 5 | 이번 장에서 다루는 것: 6 | 7 | - 서브스크립션 8 | - 커맨드 9 | -------------------------------------------------------------------------------- /ko/04-starting/01-planning.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # 계획 4 | 5 | 롤플레잉 게임을 관리하는 기본적인 어플리케이션을 만들어 보겠습니다. 6 | 7 | ### 리소스 8 | 9 | 진행하는 동안 어플리케이션의 중심이 되는 모델을 __리소스__ 라고 하겠습니다. 이 어플리케이션에서는 __플레이어들__ 입니다. 각 컴포넌트의 상태도 __모델__ 이라 부르므로 여기서 오는 혼란을 피하기 위함입니다. (예: 컴포넌트의 펼쳐진/접혀진 상태 등) 10 | 11 | ## 와이어프레임 12 | 13 | 어플리케이션은 두개의 뷰를 가집니다: 14 | 15 | ![Plan](01-planning.png) 16 | 17 | ### 화면 1 18 | 19 | 플레이어 목록을 보여줍니다. 이런 동작이 가능합니다: 20 | 21 | - 편집할 플레이어 선택 22 | 23 | ### 화면 2 24 | 25 | 특정 플레이어의 편집 화면입니다. 이런 동작이 가능합니다: 26 | 27 | - 레벨을 변경 28 | 29 | 이 어플리케이션은 아래 동작을 포함합니다: 30 | 31 | - 여러 뷰 32 | - 중첩된 컴포넌트 33 | - 리소스의 분할 34 | - 라우팅 35 | - 어플리케이션에 걸친 상태 공유 36 | - 레코드 읽기, 쓰기 37 | - Ajax 요청 38 | -------------------------------------------------------------------------------- /ko/04-starting/01-planning.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/ko/04-starting/01-planning.odg -------------------------------------------------------------------------------- /ko/04-starting/01-planning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/ko/04-starting/01-planning.png -------------------------------------------------------------------------------- /ko/04-starting/05-webpack-3.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # Webpack 3 4 | 5 | ## 기초적인 Elm 앱 6 | 7 | 기본적인 Elm 앱을 만듭니다. __src/Main.elm__ 를 작성합니다: 8 | 9 | ```elm 10 | module Main exposing (..) 11 | 12 | import Html exposing (Html, div, text, program) 13 | 14 | 15 | -- MODEL 16 | 17 | 18 | type alias Model = 19 | String 20 | 21 | 22 | init : ( Model, Cmd Msg ) 23 | init = 24 | ( "Hello", Cmd.none ) 25 | 26 | 27 | 28 | -- MESSAGES 29 | 30 | 31 | type Msg 32 | = NoOp 33 | 34 | 35 | 36 | -- VIEW 37 | 38 | 39 | view : Model -> Html Msg 40 | view model = 41 | div [] 42 | [ text model ] 43 | 44 | 45 | 46 | -- UPDATE 47 | 48 | 49 | update : Msg -> Model -> ( Model, Cmd Msg ) 50 | update msg model = 51 | case msg of 52 | NoOp -> 53 | ( model, Cmd.none ) 54 | 55 | 56 | 57 | -- SUBSCRIPTIONS 58 | 59 | 60 | subscriptions : Model -> Sub Msg 61 | subscriptions model = 62 | Sub.none 63 | 64 | 65 | 66 | -- MAIN 67 | 68 | 69 | main : Program Never Model Msg 70 | main = 71 | program 72 | { init = init 73 | , view = view 74 | , update = update 75 | , subscriptions = subscriptions 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /ko/04-starting/cover.md: -------------------------------------------------------------------------------- 1 | # 어플리케이션 만들기 2 | 3 | 이 장에서는 새로운 예제 어플리케이션을 하나 만들어 보겠습니다. 4 | 5 | 아래와 같은 내용을 다룹니다: 6 | 7 | - 어플리케이션 구조 8 | - 리소스 요청하기 9 | - 뷰 10 | - 라우팅 11 | - 사용자 상호작용과 변경사항 저장 12 | 13 | 세부사항은 다음 페이지에서 보겠습니다. 14 | -------------------------------------------------------------------------------- /ko/05-resources/01-intro.md: -------------------------------------------------------------------------------- 1 | # 리소스: 플레이어 2 | 3 | 앱에서 사용될 리소스 기준으로 앱 구조를 정리해 볼 겁니다. 지금은 리소스가 하나 밖에 (`Players`) 없으므로 `Players` 디렉토리 하나만 만들면 됩니다. 4 | 5 | `Players` 디렉토리 내부도 부모처럼 Elm 아키텍쳐의 각 컴포넌트를 모듈로 가집니다: 6 | 7 | - Players/Messages.elm 8 | - Players/Models.elm 9 | - Players/Update.elm 10 | 11 | 하지만 플레이어를 위한 다른 뷰도 있어요: 리스트와 에딧 뷰입니다. 이 뷰들도 각자의 Elm 모듈을 가집니다: 12 | 13 | - Players/List.elm 14 | - Players/Edit.elm 15 | 16 | -------------------------------------------------------------------------------- /ko/05-resources/05-main-view.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # 메인 뷰 4 | 5 | __src/View.elm__ 를 수정하여 플레이어 리스트를 추가합니다: 6 | 7 | ```elm 8 | module View exposing (..) 9 | 10 | import Html exposing (Html, div, text) 11 | import Messages exposing (Msg(..)) 12 | import Models exposing (Model) 13 | import Players.List 14 | 15 | 16 | view : Model -> Html Msg 17 | view model = 18 | div [] 19 | [ page model ] 20 | 21 | 22 | page : Model -> Html Msg 23 | page model = 24 | Html.map PlayersMsg (Players.List.view model.players) 25 | ``` 26 | 27 | -------------------------------------------------------------------------------- /ko/05-resources/06-main.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # 메인 4 | 5 | 이제 __src/Main.elm__ 이 `initialModel` 을 호출하게 합니다: 6 | 7 | ```elm 8 | module Main exposing (..) 9 | 10 | import Html exposing (Html, div, text, program) 11 | import Messages exposing (Msg) 12 | import Models exposing (Model, initialModel) 13 | import Update exposing (update) 14 | import View exposing (view) 15 | 16 | 17 | init : ( Model, Cmd Msg ) 18 | init = 19 | ( initialModel, Cmd.none ) 20 | 21 | 22 | subscriptions : Model -> Sub Msg 23 | subscriptions model = 24 | Sub.none 25 | 26 | -- MAIN 27 | 28 | main : Program Never Model Msg 29 | main = 30 | program 31 | { init = init 32 | , view = view 33 | , update = update 34 | , subscriptions = subscriptions 35 | } 36 | ``` 37 | 38 | `initialModel` 을 임포트와 `init` 에 추가했습니다. 39 | 40 | --- 41 | 42 | 어플리케이션을 실행하면 유저 하나가 포함된 리스트를 볼 수 있습니다. 43 | 44 | ![Screenshot](screenshot.png) 45 | 46 | 현재까지 진행한 코드는 와 같습니다. 47 | 48 | -------------------------------------------------------------------------------- /ko/05-resources/cover.md: -------------------------------------------------------------------------------- 1 | # 리소스 2 | 3 | 현재까지 진행된 코드는 와 같습니다. 4 | 5 | 이번 장에서는 앱에 사용될 첫 리소스: 플레이어를 추가해보겠습니다. 6 | -------------------------------------------------------------------------------- /ko/05-resources/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/ko/05-resources/screenshot.png -------------------------------------------------------------------------------- /ko/06-fetching-resources/01-plan.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # 계획 4 | 5 | 다음 단계는 앞에서 만든 API 로부터 플레이어 목록을 받아오는 겁니다. 6 | 7 | 계획은 이러합니다: 8 | 9 | ![Plan](01-plan.png) 10 | 11 | (1-2) 어플리케이션이 준비되는 동시에 플레이어들을 가져오는 Http 요청을 커맨드로 보냅니다. 이는 Html.program 의 `init` 에서 수행합니다. 12 | 13 | (3-6) 요청이 해결되면 `FetchAllDone` 메시지가 데이터와 함께 호출되고, 이는 `Players.Update` 로 전달되어 플레이어 목록을 갱신하게 됩니다. 14 | 15 | (7-10) 어플리케이션은 갱신된 플레이어 목록을 그립니다. 16 | 17 | ## 의존성 18 | 19 | `http` 모듈이 필요하므로, 아래 명령으로 설치합니다: 20 | 21 | ```bash 22 | elm package install elm-lang/http 23 | ``` 24 | -------------------------------------------------------------------------------- /ko/06-fetching-resources/01-plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/ko/06-fetching-resources/01-plan.png -------------------------------------------------------------------------------- /ko/06-fetching-resources/01-plan.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant program #white 6 | participant init #white 7 | participant Main.Update as MU #white 8 | participant Main.View as MV #white 9 | participant Players.Update as PU #white 10 | participant Players.List as PL #white 11 | 12 | program -> init 13 | init --> program : fetchAll 14 | program -> MU : (model, PlayersMsg (FetchAllDone players)) 15 | MU -> PU : (currentPlayers, FetchAllDone players) 16 | PU --> MU : Updated players' collection 17 | MU --> program : Updated app model 18 | program -> MV : App model 19 | MV -> PL : Players 20 | PL --> MV :Rendered view 21 | MV --> program : Rendered view 22 | @enduml 23 | -------------------------------------------------------------------------------- /ko/06-fetching-resources/02-players-messages.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # 플레이어 메시지 4 | 5 | 플레이어 목록을 가져오는데 필요한 메시지부터 작성해 봅시다. __src/Players/Messages.elm__ 에 새로운 임포트와 메시지를 추가합니다. 6 | 7 | ```elm 8 | module Players.Messages exposing (..) 9 | 10 | import Http 11 | import Players.Models exposing (PlayerId, Player) 12 | 13 | 14 | type Msg 15 | = OnFetchAll (Result Http.Error (List Player)) 16 | ``` 17 | 18 | 서버로부터 응답을 받으면 `OnFetchAll` 메시지가 호출됩니다. 이는 `Http.Error` 또는 가져온 플레이어 목록을 담은 `Result` 를 포함하고 있습니다. 19 | -------------------------------------------------------------------------------- /ko/06-fetching-resources/03-players-update.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # 플레이어 업데이트 4 | 5 | 플레이어 요청이 처리되면 `OnFetchAll` 메시지가 발생합니다. 6 | 7 | __src/Players/Update.elm__ 에서 이 메시지에 대응할 겁니다. `update` 를 변경합니다: 8 | 9 | ```elm 10 | ... 11 | update : Msg -> List Player -> ( List Player, Cmd Msg ) 12 | update message players = 13 | case message of 14 | OnFetchAll (Ok newPlayers) -> 15 | ( newPlayers, Cmd.none ) 16 | 17 | OnFetchAll (Err error) -> 18 | ( players, Cmd.none ) 19 | ``` 20 | 21 | 패턴 매칭으로 상황에 따른 동작을 구분합니다. 22 | 23 | - `Ok` 인 경우 가져온 플레이어로 리턴합니다. 24 | - `Err` 인 경우 일단은 변경 없이 리턴합니다. (에러를 사용자에게 표현하는게 이상적이지만, 튜토리얼을 간소화 하기 위해 생략합니다) 25 | -------------------------------------------------------------------------------- /ko/06-fetching-resources/05-main.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # 메인 4 | 5 | ## 메인 모델 6 | 7 | __src/Models.elm__ 의 하드코드된 플레이어 목록을 지웁니다 8 | 9 | ```elm 10 | initialModel : Model 11 | initialModel = 12 | { players = [] 13 | } 14 | ``` 15 | 16 | ## 메인 17 | 18 | 이제 어플리케이션 시작과 동시에 `fetchAll` 이 실행되도록 합니다. 19 | 20 | __src/Main.elm__ 을 수정합니다: 21 | 22 | ```elm 23 | ... 24 | import Messages exposing (Msg(..)) 25 | ... 26 | import Players.Commands exposing (fetchAll) 27 | 28 | init : ( Model, Cmd Msg ) 29 | init = 30 | ( initialModel, Cmd.map PlayersMsg fetchAll ) 31 | ``` 32 | 33 | 이제 어플리케이션 시작 시 `init` 에서 커맨드가 전달됩니다. 34 | -------------------------------------------------------------------------------- /ko/06-fetching-resources/06-try-it.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # 실행해 보기 4 | 5 | 돌려 봅시다! 터미널에 명령을 실행합니다: 6 | 7 | ```bash 8 | nf start 9 | ``` 10 | 11 | 브라우저에서 새로고침 할 때마다, 서버로부터 플레이어 목록을 가져와 보여줍니다. 이렇게 보일 것입니다: 12 | 13 | ![Screenshot](screenshot.png) 14 | 15 | 지금까지 진행한 코드는 이곳 에서도 볼 수 있습니다. 16 | -------------------------------------------------------------------------------- /ko/06-fetching-resources/cover.md: -------------------------------------------------------------------------------- 1 | # 리소스 가져오기 2 | 3 | 이번 장에서는 API 로부터 플레이어 컬렉션을 가져오는 일을 다룹니다. 4 | 5 | 현재까지 작업한 코드는 에서도 볼 수 있습니다. 6 | -------------------------------------------------------------------------------- /ko/06-fetching-resources/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/ko/06-fetching-resources/screenshot.png -------------------------------------------------------------------------------- /ko/07-routing/01-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/ko/07-routing/01-intro.png -------------------------------------------------------------------------------- /ko/07-routing/01-intro.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant Browser #white 6 | participant Navigation #white 7 | participant init #white 8 | participant update #white 9 | participant parseLocation #white 10 | participant View #white 11 | 12 | Navigation -> init : Current location 13 | init -> parseLocation : Location 14 | parseLocation --> init : Matched Route 15 | init --> Navigation : Initial model 16 | Navigation -> View : Model 17 | View --> Navigation : Rendered view 18 | 19 | newpage 20 | 21 | autonumber 1 "(#)" 22 | Browser -> Navigation : Location change event 23 | Navigation -> update : OnLocationChange 24 | update -> parseLocation : Location 25 | parseLocation --> update : Matched Route 26 | update --> Navigation : Updated model 27 | Navigation -> View : Model 28 | View --> Navigation : Rendered view 29 | 30 | @enduml 31 | 32 | -------------------------------------------------------------------------------- /ko/07-routing/01-intro_001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/ko/07-routing/01-intro_001.png -------------------------------------------------------------------------------- /ko/07-routing/04-main-model.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # 메인 모델 4 | 5 | 현재 루트를 메인 어플리케이션 모델에 저장할 겁니다. 6 | __src/Models.elm__ 을 변경합니다: 7 | 8 | ```elm 9 | module Models exposing (..) 10 | 11 | import Players.Models exposing (Player) 12 | import Routing 13 | 14 | 15 | type alias Model = 16 | { players : List Player 17 | , route : Routing.Route 18 | } 19 | 20 | 21 | initialModel : Routing.Route -> Model 22 | initialModel route = 23 | { players = [] 24 | , route = route 25 | } 26 | ``` 27 | 28 | 여기서는: 29 | 30 | - `route` 를 모델에 추가했습니다. 31 | - `initialModel` 이 `route` 를 받도록 했습니다. 32 | -------------------------------------------------------------------------------- /ko/07-routing/05-main-messages.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # 메인 메시지 4 | 5 | 브라우저 경로가 바뀔 때 사용할 새 메시지가 필요합니다. 6 | 7 | __src/Messages.elm__ 를 바꿉니다: 8 | 9 | ```elm 10 | module Messages exposing (..) 11 | 12 | import Navigation exposing (Location) 13 | import Players.Messages 14 | 15 | 16 | type Msg 17 | = PlayersMsg Players.Messages.Msg 18 | | OnLocationChange Location 19 | ``` 20 | 21 | - `Navigation` 을 임포트하고 있습니다. 22 | - `OnLocationChange Location` 메시지를 추가했습니다. 23 | -------------------------------------------------------------------------------- /ko/07-routing/06-main-update.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # 메인 업데이트 4 | 5 | 메인 `update` 함수에도 새 `OnLocationChange` 메시지를 위한 로직이 필요합니다. 6 | 7 | __src/Update.elm__ 에 아래 분기를 추가합니다: 8 | 9 | ```elm 10 | ... 11 | import Routing exposing (parseLocation) 12 | 13 | ... 14 | 15 | update msg model = 16 | case msg of 17 | ... 18 | OnLocationChange location -> 19 | let 20 | newRoute = 21 | parseLocation location 22 | in 23 | ( { model | route = newRoute }, Cmd.none ) 24 | ``` 25 | 26 | `OnLocationChange` 메시지를 받아 경로를 파싱하여 루트를 구하고 모델을 변경하고 있습니다. 27 | -------------------------------------------------------------------------------- /ko/07-routing/09-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/ko/07-routing/09-edit.png -------------------------------------------------------------------------------- /ko/07-routing/09-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/ko/07-routing/09-list.png -------------------------------------------------------------------------------- /ko/07-routing/09-try-it.md: -------------------------------------------------------------------------------- 1 | # 실행해 보기 2 | 3 | 지금까지 한 걸 테스트해 봅시다. 어플리케이션을 실행합니다: 4 | 5 | ```bash 6 | nf start 7 | ``` 8 | 9 | 브라우저에서 `http://localhost:3000` 을 엽니다. 플레이어 목록을 볼 수 있습니다. 10 | 11 | ![screenshot](09-list.png) 12 | 13 | `http://localhost:3000/#players/2` 로 가면 플레이어 하나를 볼 수 있습니다. 14 | 15 | ![screenshot](09-edit.png) 16 | 17 | 다음에는 페이지 내부에서 이동 가능하도록 만들어 보겠습니다. 18 | 19 | 현재까지 진행한 코드는 다음과 같습니다. 20 | -------------------------------------------------------------------------------- /ko/07-routing/cover.md: -------------------------------------------------------------------------------- 1 | # 라우팅 2 | 3 | 이번 장에서는 어플리케이션에 라우팅을 추가합니다. 4 | 5 | 현재까지 진행한 코드는 에서도 볼 수 있습니다. 6 | -------------------------------------------------------------------------------- /ko/08-edit/01-plan.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # 계획 4 | 5 | 플레이어 레벨 변경 기능을 위한 계획은 다음과 같습니다: 6 | 7 | ![Flow](01-plan.png) 8 | 9 | (1) 사용자가 increase 나 decrease 버튼을 누르면 `ChangeLevel` 에 `playerId` 와 `howMuch` 를 담아 호출합니다. 10 | 11 | (2) __Html.program__ (Navigation.program 이 감싸고 있는) 은 이 메시지를 `Main.Update` 로 전달하고 메인에서는 `Players.Update` 로 전달합니다. (3) 12 | 13 | (4) `Players.Update` 는 백엔드 저장을 위한 커맨드를 리턴하고, 이 커맨드는 __Html.program__ 으로 흘러갑니다. (5) 14 | 15 | (6) Elm 런타임에서 커맨드를 실행 (API 호출) 하고 우리는 성공 혹은 실패라는 결과를 받습니다. 성공인 경우 `SaveSuccess` 메시지가 갱신된 플레이어와 함께 호출됩니다. 16 | 17 | (7) `Main.Update` 는 `SaveSuccess` 메시지를 `Player.Update` 로 보냅니다. 18 | 19 | (8) `Player.Update` 에서 `players` 모델을 업데이트해서 리턴합니다. 이는 Html.program 으로 전달됩니다. (9) 20 | 21 | (10) Html.program 은 바뀐 모델로 뷰를 그립니다. 22 | -------------------------------------------------------------------------------- /ko/08-edit/01-plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/ko/08-edit/01-plan.png -------------------------------------------------------------------------------- /ko/08-edit/01-plan.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant Html.program as program #white 6 | participant Main.Update as MU #white 7 | participant Main.View as MV #white 8 | participant Players.Update as PU #white 9 | participant Players.Edit as PE #white 10 | 11 | PE -> program : PlayersMsg (ChangeLevel playerId howMuch) 12 | program -> MU : PlayersMsg (ChangeLevel playerId howMuch) 13 | MU -> PU : ChangeLevel playerId howMuch 14 | PU --> MU : Command to save 15 | MU --> program : Command to save 16 | ||| 17 | program -> MU : PlayersMsg (SaveSuccess player) 18 | MU -> PU : (SaveSuccess player) 19 | PU --> MU : Updated players 20 | MU --> program : Updated model 21 | program -> MV : Updated model 22 | 23 | 24 | @enduml 25 | 26 | -------------------------------------------------------------------------------- /ko/08-edit/02-messages.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | # 메시지 4 | 5 | 필요한 메시지부터 추가해 봅시다. 6 | 7 | __src/Players/Messages.elm__ 에 추가합니다: 8 | 9 | ```elm 10 | type Msg 11 | ... 12 | | ChangeLevel PlayerId Int 13 | | OnSave (Result Http.Error Player) 14 | ``` 15 | 16 | - `ChangeLevel` 은 사용자가 레벨 변경을 시도할 때 생성됩니다. 두번째 인자는 레벨이 얼만큼 변경되어야 하는지를 가리키는 정수입니다. (예: -1 은 감소, 1 은 증가) 17 | - 이후 API 에 플레이어 업데이트 요청을 보냅니다. API 에서 응답이 오면 `OnSave` 가 호출됩니다. 18 | - `OnSave` 는 성공인 경우 업데이트된 플레이어를, 실패인 경우 Http 에러 객체를 포함합니다. 19 | -------------------------------------------------------------------------------- /ko/08-edit/03-player-edit.md: -------------------------------------------------------------------------------- 1 | > This page covers Elm 0.18 2 | 3 | ## 플레이어 편집 뷰 4 | 5 | 앞에서 `ChangeLevel` 메시지를 만들었습니다. 플레이어 편집 뷰에서 이 메시지가 호출되도록 해 봅시다. 6 | 7 | __src/Players/Edit.elm__ 에서 `btnLevelDecrease` 와 `btnLevelIncrease` 를 변경합니다: 8 | 9 | ```elm 10 | ... 11 | btnLevelDecrease : Player -> Html Msg 12 | btnLevelDecrease player = 13 | a [ class "btn ml1 h1", onClick (ChangeLevel player.id -1) ] 14 | [ i [ class "fa fa-minus-circle" ] [] ] 15 | 16 | 17 | btnLevelIncrease : Player -> Html Msg 18 | btnLevelIncrease player = 19 | a [ class "btn ml1 h1", onClick (ChangeLevel player.id 1) ] 20 | [ i [ class "fa fa-plus-circle" ] [] ] 21 | ``` 22 | 23 | `onClick (ChangeLevel player.id howMuch)` 를 두 버튼에 추가했습니다. `howMuch` 는 감소인 경우 `-1` 이 되고 증가인 경우 `1` 이 됩니다. 24 | -------------------------------------------------------------------------------- /ko/08-edit/cover.md: -------------------------------------------------------------------------------- 1 | # 편집 2 | 3 | 마지막 장인 여기서는 플레이어의 레벨을 편집하고 백엔드에 저장되는 기능을 추가해 보겠습니다. 4 | 5 | 현재까지 진행한 코드는 여기서도 볼 수 있습니다. 6 | -------------------------------------------------------------------------------- /ko/09-conclusion/01-improvements.md: -------------------------------------------------------------------------------- 1 | # 개선점 2 | 3 | 우리 앱에 적용해 볼 만한 개선점 목록입니다. 4 | 5 | ## 플레이어 생성과 삭제 6 | 7 | 튜토리얼을 짧게 유지하기 위해 생략했지만, 매우 중요한 기능입니다. 8 | 9 | ## 플레이어 이름 변경 10 | 11 | ## Http 요청 실패 시 에러 표시 12 | 13 | 현재 플레이어를 가져오거나 저장하는 데 실패하는 경우 딱히 하는 일이 없습니다. 사용자에게 에러 메시지를 보여 줄 수 있다면 좋을 겁니다. 14 | 15 | ## 더 나은 에러 메시지 16 | 17 | 에러 메시지를 그냥 보여주기만 하는 것보다 더 좋은 것은: 18 | 19 | - 메시지를 타입별로 표시 (예: 에러, 정보 등) 20 | - 동시에 여러 메시지 표시 가능 21 | - 메시지 닫기 가능 22 | - 메시지가 몇 초 지나면 자동으로 사라짐 23 | 24 | ## 긍정적 (Optimistic) 업데이트 25 | 26 | 현재 모든 업데이트 함수는 비관적입니다. 서버로부터 성공적인 응답을 받을 때까지 모델을 변경하지 않는다는 이야기지요. 긍정적인 생성, 업데이트, 삭제 기능을 넣는다면 큰 개선점이 될 것입니다. 하지만 더 나은 에러 처리도 필요하겠죠. 27 | 28 | ## 유효성 검사 (Validations) 29 | 30 | 이름이 없는 플레이어는 피해야겠죠. 플레이어 이름이 빈 값이 될 수 없도록 유효성 검사를 한다면 좋은 기능이 될 겁니다. 31 | 32 | ## 특징과 보너스 추가 33 | 34 | 플레이어가 갖는 특징의 목록을 만들 수 있을 겁니다. 특징은 장비, 의복, 스크롤, 액세서리 같은 겁니다. (예: "강철 검" 등) 그러면 플레이어와 특징간 연결도 지을 수 있을 겁니다. 35 | 36 | 각 특징은 연관 보너스를 가집니다. 플레이어는 각자의 레벨에 보너스의 총합을 더하는 식으로 위력을 계산할 수 있습니다. 37 | 38 | --- 39 | 40 | 기능이 추가된 버전의 앱은 이곳의 마스터 브랜치를 참조하세요. 41 | -------------------------------------------------------------------------------- /ko/09-conclusion/cover.md: -------------------------------------------------------------------------------- 1 | # 마무리 2 | 3 | 튜토리얼은 끝났습니다. 하지만 몇가지 개선과 기능추가에 대한 내용이 있으니 한번 읽어 보세요. 4 | 5 | 저는 이 튜토리얼을 개선하는 데 항상 귀를 기울이고 있습니다. 에 이슈를 열어 주세요. 6 | 7 | 감사합니다! 8 | -------------------------------------------------------------------------------- /ko/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/ko/logo.png -------------------------------------------------------------------------------- /ko/tips-tricks/context.md: -------------------------------------------------------------------------------- 1 | # 감싸기 2 | 3 | 일반적으로 `update` 나 `view` 함수는 이렇게 생겼습니다: 4 | 5 | ```elm 6 | view : Model -> Html Msg 7 | view model = 8 | ... 9 | ``` 10 | 11 | 혹은 12 | 13 | ```elm 14 | update : Msg -> Model -> (Model, Cmd Msg) 15 | update message model = 16 | ... 17 | ``` 18 | 19 | 이 컴포넌트에 속하는 `Model` 만을 인자로 사용해야 한다는 생각에 갇히기 쉽습니다. 가끔은 부가적인 정보가 필요할 때도 있고 이는 물론 가능합니다. 예를 들면: 20 | 21 | ```elm 22 | type alias Context = 23 | { model : Model 24 | , time : Time 25 | } 26 | 27 | view : Context -> Html Msg 28 | view context = 29 | ... 30 | ``` 31 | 32 | 이 함수는 컴포넌트의 모델에 추가적으로 부모의 모델로부터 `time` 을 받습니다. 33 | -------------------------------------------------------------------------------- /ko/tips-tricks/troubleshooting.md: -------------------------------------------------------------------------------- 1 | # 문제 해결 2 | 3 | 개발 중 컴파일러가 아무래도 이상하게 동작하는 것 같다면 `elm-stuff/build-artifacts` 를 지우고 다시 컴파일해 보세요. 어지간한 경우 해결됩니다. 4 | -------------------------------------------------------------------------------- /zh-TW/01-foundations/01-hello.elm: -------------------------------------------------------------------------------- 1 | module Hello exposing (..) 2 | 3 | import Html exposing (text) 4 | 5 | 6 | main = 7 | text "Hello" 8 | -------------------------------------------------------------------------------- /zh-TW/01-foundations/06-type-aliases.md: -------------------------------------------------------------------------------- 1 | # 型別別名(aliases) 2 | 3 | 顧名思義型別別名是一種別名功能。舉例來說,Elm 核心有 `Int` 及 `String` 兩種型別。你可以為它們新增別名: 4 | 5 | ```elm 6 | type alias PlayerId = Int 7 | 8 | type alias PlayerName = String 9 | ``` 10 | 11 | 上述幾個別名單純指名別的核心型別。像是下述函式,特別有用: 12 | 13 | ```elm 14 | label: Int -> String 15 | ``` 16 | 17 | 可以改寫成: 18 | 19 | ```elm 20 | label: PlayerId -> PlayerName 21 | ``` 22 | 23 | 這樣的函式更加清楚、明瞭。 24 | 25 | ## 紀錄(Records) 26 | 27 | 紀錄定義式看起來像是: 28 | 29 | ```elm 30 | { id : Int 31 | , name : String 32 | } 33 | ``` 34 | 35 | 如果你想在函式使用紀錄,可以這樣撰寫標記式: 36 | 37 | ```elm 38 | label: { id : Int, name : String } -> String 39 | ``` 40 | 41 | 有些冗長,這時候型別別名就很有用: 42 | 43 | ```elm 44 | type alias Player = 45 | { id : Int 46 | , name : String 47 | } 48 | 49 | label: Player -> String 50 | ``` 51 | 52 | 新增一個 `Player` 型別別名,指到一個紀錄定義式。接著在函式標記式使用這個別名。 53 | 54 | ## 建構子(Constructors) 55 | 56 | 型別別名也可以用來當作__建構子__函式使用。可以把型別別名當作函式一樣使用,建立出紀錄。 57 | 58 | ```elm 59 | type alias Player = 60 | { id : Int 61 | , name : String 62 | } 63 | 64 | Player 1 "Sam" 65 | ==> { id = 1, name = "Sam" } 66 | ``` 67 | 68 | 上述新增一個 `Player` 型別別名。接著,如同函式一般呼叫 `Player` 型別別名,帶入兩個參數。這會傳回一個紀錄並帶有適當的屬性。請注意到,參數的先後順序決定哪個屬性有的值。 69 | -------------------------------------------------------------------------------- /zh-TW/01-foundations/07-unit-type.md: -------------------------------------------------------------------------------- 1 | # 單位型別(The unit type) 2 | 3 | Elm 中,空的 tuple `()` 稱之為__單位型別__。這個十分的普及,值得作些解說。 4 | 5 | 考慮某一個型別別名,並帶有__型別變數__(使用 `a` 代表): 6 | 7 | ```elm 8 | type alias Message a = 9 | { code : String 10 | , body : a 11 | } 12 | ``` 13 | 14 | 可以讓某個函式預期有個 `Message` 型別,裡面的 `body` 是 `String` 型別,像是: 15 | 16 | ```elm 17 | readMessage : Message String -> String 18 | readMessage message = 19 | ... 20 | ``` 21 | 22 | 或某個函式預期有個 `Message` 型別,裡面的 `body` 是整數串列的型別: 23 | 24 | ```elm 25 | readMessage : Message (List Int) -> String 26 | readMessage message = 27 | ... 28 | ``` 29 | 30 | 但如果某個函式並不需要 body 有值呢?可以使用單位型別來指出 body 必須為空值: 31 | 32 | ```elm 33 | readMessage : Message () -> String 34 | readMessage message = 35 | ... 36 | ``` 37 | 38 | 上述函式取用 `Message` 型別,帶有__空的 body__。這跟__任意值__不同,就是個__空__值。 39 | 40 | 所以,單位型別常見用來作為空值的保留位置(placeholder)。 41 | 42 | ## 任務(Task) 43 | 44 | 實際應用中 `Task` 型別就是個範例。當使用 `Task` 時,你會常看到單位型別。 45 | 46 | 典型的任務會有 __錯誤__ 及 __結果__。 47 | 48 | ```elm 49 | Task error result 50 | ``` 51 | 52 | - 有時候,我們想要一種任務可以忽略錯誤:`Task () result` 53 | - 或者,可以忽略結果:`Tasks error ()` 54 | - 又或者,兩者皆可忽略:`Task () ()` 55 | -------------------------------------------------------------------------------- /zh-TW/01-foundations/cover.md: -------------------------------------------------------------------------------- 1 | # 基礎 2 | 3 | 此章節包含: 4 | 5 | - 執行基本的 Elm 應用程式 6 | - Elm 基本的函式與型別 7 | -------------------------------------------------------------------------------- /zh-TW/02-elm-arch/01-introduction.elm: -------------------------------------------------------------------------------- 1 | module App exposing (..) 2 | 3 | import Html exposing (Html, div, text, program) 4 | 5 | 6 | -- MODEL 7 | 8 | 9 | type alias Model = 10 | String 11 | 12 | 13 | init : ( Model, Cmd Msg ) 14 | init = 15 | ( "Hello", Cmd.none ) 16 | 17 | 18 | 19 | -- MESSAGES 20 | 21 | 22 | type Msg 23 | = NoOp 24 | 25 | 26 | 27 | -- VIEW 28 | 29 | 30 | view : Model -> Html Msg 31 | view model = 32 | div [] 33 | [ text model ] 34 | 35 | 36 | 37 | -- UPDATE 38 | 39 | 40 | update : Msg -> Model -> ( Model, Cmd Msg ) 41 | update msg model = 42 | case msg of 43 | NoOp -> 44 | ( model, Cmd.none ) 45 | 46 | 47 | 48 | -- SUBSCRIPTIONS 49 | 50 | 51 | subscriptions : Model -> Sub Msg 52 | subscriptions model = 53 | Sub.none 54 | 55 | 56 | 57 | -- MAIN 58 | 59 | 60 | main : Program Never Model Msg 61 | main = 62 | program 63 | { init = init 64 | , view = view 65 | , update = update 66 | , subscriptions = subscriptions 67 | } 68 | -------------------------------------------------------------------------------- /zh-TW/02-elm-arch/04-flow.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # 應用程式流(Application flow) 4 | 5 | 下圖描繪出 Html.App 如何與應用程式交互作用。 6 | 7 | ![Flow](04-flow.png) 8 | 9 | 1. Html.App 呼叫視界函式並帶入初始模型進行轉譯。 10 | 1. 當使用者點擊 Expand 按鈕,視界觸發 `Expand` 訊息。 11 | 1. Html.App 收到 `Expand` 訊息,呼叫 `更新` 函式帶入 `Expand` 訊息及目前應用程式的狀態 12 | 1. 更新函式回應訊息,傳回更新後狀態及欲執行的命令(或 `Cmd.none`)。 13 | 1. Html.App 收到更新後狀態,儲存,呼叫視界函式並帶入更新後狀態。 14 | 15 | 通常 Html.App 是 Elm 應用程式唯一持有狀態的地方,它是一個集中的大型狀態樹。 16 | -------------------------------------------------------------------------------- /zh-TW/02-elm-arch/04-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/zh-TW/02-elm-arch/04-flow.png -------------------------------------------------------------------------------- /zh-TW/02-elm-arch/04-flow.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber 3 | participant program #white 4 | participant update #white 5 | participant view #white 6 | 7 | program -> view : Render view 8 | ||| 9 | view -> program : Trigger message e.g. Expand 10 | program -> update : Send message with the current state 11 | update --> program : Return updated state and command 12 | program -> view : Render view 13 | @enduml 14 | -------------------------------------------------------------------------------- /zh-TW/02-elm-arch/05-msg-payload.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (Html, button, div, text, program) 4 | import Html.Events exposing (onClick) 5 | 6 | 7 | -- MODEL 8 | 9 | 10 | type alias Model = 11 | Int 12 | 13 | 14 | init : ( Model, Cmd Msg ) 15 | init = 16 | ( 0, Cmd.none ) 17 | 18 | 19 | 20 | -- MESSAGES 21 | 22 | 23 | type Msg 24 | = Increment Int 25 | 26 | 27 | 28 | -- VIEW 29 | 30 | 31 | view : Model -> Html Msg 32 | view model = 33 | div [] 34 | [ button [ onClick (Increment 2) ] [ text "+" ] 35 | , text (toString model) 36 | ] 37 | 38 | 39 | 40 | -- UPDATE 41 | 42 | 43 | update : Msg -> Model -> ( Model, Cmd Msg ) 44 | update msg model = 45 | case msg of 46 | Increment howMuch -> 47 | ( model + howMuch, Cmd.none ) 48 | 49 | 50 | 51 | -- SUBSCRIPTIONS 52 | 53 | 54 | subscriptions : Model -> Sub Msg 55 | subscriptions model = 56 | Sub.none 57 | 58 | 59 | 60 | -- MAIN 61 | 62 | 63 | main : Program Never Model Msg 64 | main = 65 | program 66 | { init = init 67 | , view = view 68 | , update = update 69 | , subscriptions = subscriptions 70 | } 71 | -------------------------------------------------------------------------------- /zh-TW/02-elm-arch/06-composing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/zh-TW/02-elm-arch/06-composing.png -------------------------------------------------------------------------------- /zh-TW/02-elm-arch/06-composing.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber "(#)" 3 | participant User #white 4 | participant program #white 5 | participant Main.initialModel as Mim #white 6 | participant Main.view as MV #white 7 | participant Main.update as MU #white 8 | participant Widget.initialModel as Wim #white 9 | participant Widget.view as WV #white 10 | participant Widget.update as WU #white 11 | 12 | program -> Mim: initialModel 13 | Mim -> Wim: initialModel 14 | Wim --> Mim: widgetModel 15 | Mim --> program: mainModel 16 | program -> MV : mainModel 17 | MV -> WV : widgetModel 18 | WV --> MV : Html 19 | MV --> program : Html 20 | program -> User : Html 21 | 22 | newpage 23 | 24 | autonumber 1 "(#)" 25 | User -> WV : Click 26 | WV -> MV: Increase 27 | MV -> program: (WidgetMsg Increase) 28 | program -> MU: (WidgetMsg Increase) mainModel 29 | MU -> WU : Increase widgetModel 30 | WU --> MU: (updated widgetModel, command) 31 | MU --> program: (updated mainModel, command) 32 | program -> MV : mainModel 33 | MV -> WV : widgetModel 34 | WV --> MV : Html 35 | MV --> program : Html 36 | @enduml 37 | -------------------------------------------------------------------------------- /zh-TW/02-elm-arch/06-composing/Widget.elm: -------------------------------------------------------------------------------- 1 | module Widget exposing (..) 2 | 3 | import Html exposing (Html, button, div, text) 4 | import Html.Events exposing (onClick) 5 | 6 | 7 | -- MODEL 8 | 9 | 10 | type alias Model = 11 | { count : Int 12 | } 13 | 14 | 15 | initialModel : Model 16 | initialModel = 17 | { count = 0 18 | } 19 | 20 | 21 | type Msg 22 | = Increase 23 | 24 | 25 | 26 | -- VIEW 27 | 28 | 29 | view : Model -> Html Msg 30 | view model = 31 | div [] 32 | [ div [] [ text (toString model.count) ] 33 | , button [ onClick Increase ] [ Html.text "Click" ] 34 | ] 35 | 36 | 37 | 38 | -- UPDATE 39 | 40 | 41 | update : Msg -> Model -> ( Model, Cmd Msg ) 42 | update message model = 43 | case message of 44 | Increase -> 45 | ( { model | count = model.count + 1 }, Cmd.none ) 46 | -------------------------------------------------------------------------------- /zh-TW/02-elm-arch/06-composing/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 | }, 14 | "elm-version": "0.18.0 <= v < 0.19.0" 15 | } -------------------------------------------------------------------------------- /zh-TW/02-elm-arch/06-composing_001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/zh-TW/02-elm-arch/06-composing_001.png -------------------------------------------------------------------------------- /zh-TW/02-elm-arch/cover.md: -------------------------------------------------------------------------------- 1 | # Elm 架構 2 | 3 | 本章節包含: 4 | 5 | - Elm 架構基本概論 6 | - Html.App.program 介紹 7 | - 訊息(Messages) 8 | - 命令(Commands) 9 | - 訂閱(Subscriptions) 10 | -------------------------------------------------------------------------------- /zh-TW/03-subs-cmds/02-commands.elm: -------------------------------------------------------------------------------- 1 | module Main exposing (..) 2 | 3 | import Html exposing (Html, div, button, text, program) 4 | import Html.Events exposing (onClick) 5 | import Random 6 | 7 | 8 | -- MODEL 9 | 10 | 11 | type alias Model = 12 | Int 13 | 14 | 15 | init : ( Model, Cmd Msg ) 16 | init = 17 | ( 1, Cmd.none ) 18 | 19 | 20 | 21 | -- MESSAGES 22 | 23 | 24 | type Msg 25 | = Roll 26 | | OnResult Int 27 | 28 | 29 | 30 | -- VIEW 31 | 32 | 33 | view : Model -> Html Msg 34 | view model = 35 | div [] 36 | [ button [ onClick Roll ] [ text "Roll" ] 37 | , text (toString model) 38 | ] 39 | 40 | 41 | 42 | -- UPDATE 43 | 44 | 45 | update : Msg -> Model -> ( Model, Cmd Msg ) 46 | update msg model = 47 | case msg of 48 | Roll -> 49 | ( model, Random.generate OnResult (Random.int 1 6) ) 50 | 51 | OnResult res -> 52 | ( res, Cmd.none ) 53 | 54 | 55 | 56 | -- MAIN 57 | 58 | 59 | main : Program Never Model Msg 60 | main = 61 | program 62 | { init = init 63 | , view = view 64 | , update = update 65 | , subscriptions = (always Sub.none) 66 | } 67 | -------------------------------------------------------------------------------- /zh-TW/03-subs-cmds/02-commands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/zh-TW/03-subs-cmds/02-commands.png -------------------------------------------------------------------------------- /zh-TW/03-subs-cmds/02-commands.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | autonumber "(#)" 3 | 4 | participant program #white 5 | participant Main.update as MU #white 6 | participant Child.update as CU #white 7 | participant GrandChild.update as GC #white 8 | 9 | program -> MU: update 10 | MU -> CU: update 11 | CU -> GC: update 12 | GC --> CU: (model, command) 13 | CU --> MU: (model, command) 14 | MU -> program : (model, command) 15 | 16 | @enduml 17 | -------------------------------------------------------------------------------- /zh-TW/03-subs-cmds/cover.md: -------------------------------------------------------------------------------- 1 | # 訂閱(Subscriptions)與命令(Commands) 2 | 3 | 為了在應用程式中監聽外部輸入且創造__副作用__,我們需要學習__訂閱__、__命令__及__任務__。 4 | 5 | 此章節包含: 6 | 7 | - 訂閱 8 | - 命令 9 | - 任務 10 | -------------------------------------------------------------------------------- /zh-TW/04-starting/01-planning.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # 規劃 4 | 5 | 我們將建造一個基本的應用程式,用來追蹤一個虛構的角色扮演遊戲。 6 | 7 | ### 資源(Resources) 8 | 9 | 因為應用程式的關係,接下來的章節將會使用__資源__來表示模型。應用程式中有__玩家(players)__。使用__模型__可能會造成混淆,因為元件特定狀態也是一種模型(例如展開/收合的元件狀態)。 10 | 11 | ## 線框圖(Wireframes) 12 | 13 | 應用程式有兩個畫面: 14 | 15 | ![Plan](01-planning.png) 16 | 17 | ### 畫面 1 18 | 19 | 顯示玩家列表頁面。從這可以: 20 | 21 | - 瀏覽至玩家編輯頁面 22 | 23 | ### 畫面 2 24 | 25 | 顯示玩家編輯頁面。這個畫面中可以: 26 | 27 | - 更改等級 28 | 29 | 這是個非常簡單的應用程式,展示了: 30 | 31 | - 多重視界(Multiple views) 32 | - 巢狀元件 33 | - 拆解應用程式成各種資源 34 | - 路由 35 | - 共享應用程式的狀態 36 | - 讀取及編輯紀錄 37 | - Ajax 請求 38 | -------------------------------------------------------------------------------- /zh-TW/04-starting/01-planning.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/zh-TW/04-starting/01-planning.odg -------------------------------------------------------------------------------- /zh-TW/04-starting/01-planning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/zh-TW/04-starting/01-planning.png -------------------------------------------------------------------------------- /zh-TW/04-starting/04-webpack-2.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # Webpack 2 4 | 5 | ## index.html 6 | 7 | 因為不再使用 Elm reactor,所以需要新增 HTML 來引入應用程式。新增 __src/index.html__: 8 | 9 | ```html 10 | 11 | 12 | 13 | 14 | Elm SPA example 15 | 16 | 17 |
18 | 19 | 20 | 21 | ``` 22 | 23 | ## index.js 24 | 25 | 這是 Webpack 建立綑綁的進入點。新增 __src/index.js__: 26 | 27 | ```js 28 | 'use strict'; 29 | 30 | require('ace-css/css/ace.css'); 31 | require('font-awesome/css/font-awesome.css'); 32 | 33 | // 引入 index.html,這樣才會被複製到 dist 目錄 34 | require('./index.html'); 35 | 36 | var Elm = require('./Main.elm'); 37 | var mountNode = document.getElementById('main'); 38 | 39 | // 第三個放入 embed 的值是程式初始值,例如 userID 或 token。 40 | var app = Elm.Main.embed(mountNode); 41 | ``` 42 | 43 | ## 安裝 Elm 包 44 | 45 | 執行: 46 | 47 | ```bash 48 | elm-package install elm-lang/html 49 | ``` 50 | 51 | ## 程式碼目錄 52 | 53 | 將所有程式碼都放在 `src` 目錄底下,需要告訴 Elm 去哪找相依套件。對 __elm-package.json__ 做修改: 54 | 55 | ```json 56 | ... 57 | "source-directories": [ 58 | "src" 59 | ], 60 | ... 61 | ``` 62 | 63 | 少了這個設定,Elm 編譯器將會試著從專案根目錄開始找起匯入,因此會失敗。 64 | -------------------------------------------------------------------------------- /zh-TW/04-starting/05-webpack-3.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # Webpack 3 4 | 5 | ## 初始化 Elm 應用程式 6 | 7 | 建立基本 Elm 應用程式。修改 __src/Main.elm__: 8 | 9 | ```elm 10 | module Main exposing (..) 11 | 12 | import Html exposing (Html, div, text, program) 13 | 14 | 15 | -- MODEL 16 | 17 | 18 | type alias Model = 19 | String 20 | 21 | 22 | init : ( Model, Cmd Msg ) 23 | init = 24 | ( "Hello", Cmd.none ) 25 | 26 | 27 | 28 | -- MESSAGES 29 | 30 | 31 | type Msg 32 | = NoOp 33 | 34 | 35 | 36 | -- VIEW 37 | 38 | 39 | view : Model -> Html Msg 40 | view model = 41 | div [] 42 | [ text model ] 43 | 44 | 45 | 46 | -- UPDATE 47 | 48 | 49 | update : Msg -> Model -> ( Model, Cmd Msg ) 50 | update msg model = 51 | case msg of 52 | NoOp -> 53 | ( model, Cmd.none ) 54 | 55 | 56 | 57 | -- SUBSCRIPTIONS 58 | 59 | 60 | subscriptions : Model -> Sub Msg 61 | subscriptions model = 62 | Sub.none 63 | 64 | 65 | 66 | -- MAIN 67 | 68 | 69 | main : Program Never Model Msg 70 | main = 71 | program 72 | { init = init 73 | , view = view 74 | , update = update 75 | , subscriptions = subscriptions 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /zh-TW/04-starting/cover.md: -------------------------------------------------------------------------------- 1 | # 開發應用程式 2 | 3 | 本章節我們開始建置一個 Elm 應用程式。 4 | 5 | 內容將會包括下列各個應用程式面向: 6 | 7 | - 應用程式結構 8 | - 擷取資源 9 | - 視界 10 | - 路由 11 | - 使用者互動與儲存更改 12 | 13 | 下一頁有關更詳細的應用程式。 14 | -------------------------------------------------------------------------------- /zh-TW/05-resources/01-intro.md: -------------------------------------------------------------------------------- 1 | # 玩家(Players)資源 2 | 3 | 根據資源的名稱來組織應用程式的架構。這個應用程式中,只有一個資源(`Players`),所以只有一個 `Players` 資料夾。 4 | 5 | `Players` 資料夾將會有跟主階層相同的模組,Elm 架構的一個元件一個模組: 6 | 7 | - Players/Messages.elm 8 | - Players/Models.elm 9 | - Players/Update.elm 10 | 11 | 然而,也會有玩家不同的視界:列表及編輯視界。每個視界都會有自己的 Elm 模組: 12 | 13 | - Players/List.elm 14 | - Players/Edit.elm 15 | 16 | -------------------------------------------------------------------------------- /zh-TW/05-resources/05-main-view.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # 主視界(Main view) 4 | 5 | 修改 __src/View.elm__ 包含玩家列表: 6 | 7 | ```elm 8 | module View exposing (..) 9 | 10 | import Html exposing (Html, div, text) 11 | import Messages exposing (Msg(..)) 12 | import Models exposing (Model) 13 | import Players.List 14 | 15 | 16 | view : Model -> Html Msg 17 | view model = 18 | div [] 19 | [ page model ] 20 | 21 | 22 | page : Model -> Html Msg 23 | page model = 24 | Html.map PlayersMsg (Players.List.view model.players) 25 | ``` 26 | 27 | -------------------------------------------------------------------------------- /zh-TW/05-resources/06-main.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # 主程式(Main) 4 | 5 | 最後,修改 __src/Main.elm__ 呼叫 `initialModel`: 6 | 7 | ```elm 8 | module Main exposing (..) 9 | 10 | import Html exposing (Html, div, text, program) 11 | import Messages exposing (Msg) 12 | import Models exposing (Model, initialModel) 13 | import Update exposing (update) 14 | import View exposing (view) 15 | 16 | 17 | init : ( Model, Cmd Msg ) 18 | init = 19 | ( initialModel, Cmd.none ) 20 | 21 | 22 | subscriptions : Model -> Sub Msg 23 | subscriptions model = 24 | Sub.none 25 | 26 | -- 主程式 27 | 28 | main : Program Never Model Msg 29 | main = 30 | program 31 | { init = init 32 | , view = view 33 | , update = update 34 | , subscriptions = subscriptions 35 | } 36 | ``` 37 | 38 | 在匯入及 `init` 新增 `initialModel`。 39 | 40 | --- 41 | 42 | 當執行應用程式時,會看見列表中有一位用戶。 43 | 44 | ![Screenshot](screenshot.png) 45 | 46 | 應用程式看起來像是 47 | -------------------------------------------------------------------------------- /zh-TW/05-resources/cover.md: -------------------------------------------------------------------------------- 1 | # 資源(Resources) 2 | 3 | 目前為止,你的程式碼看起來像是 4 | 5 | 這個章節將會加入第一個資源到應用程式:玩家。 6 | -------------------------------------------------------------------------------- /zh-TW/05-resources/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/zh-TW/05-resources/screenshot.png -------------------------------------------------------------------------------- /zh-TW/06-fetching-resources/01-plan.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # 規劃 4 | 5 | 接下來是從 API 擷取玩家清單。 6 | 7 | 以下是規劃: 8 | 9 | ![Plan](01-plan.png) 10 | 11 | (1-2) 當載入應用程式時,觸發擷取玩家的 Http 請求。這部份在 Html.App 的 `init` 完成。 12 | 13 | (3-6) 當請求完成,觸發 `FetchAllDone` 伴隨著資料,訊息流到 `Players.Update`,將會更新玩家的集合。 14 | 15 | (7-10) 接著,應用程式轉譯更新後的玩家列表。 16 | 17 | ## 函式依賴 18 | 19 | 我們需要 `http`,執行下列指令安裝: 20 | 21 | ```bash 22 | elm package install elm-lang/http 23 | ``` 24 | -------------------------------------------------------------------------------- /zh-TW/06-fetching-resources/01-plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/zh-TW/06-fetching-resources/01-plan.png -------------------------------------------------------------------------------- /zh-TW/06-fetching-resources/01-plan.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant program #white 6 | participant init #white 7 | participant Main.Update as MU #white 8 | participant Main.View as MV #white 9 | participant Players.Update as PU #white 10 | participant Players.List as PL #white 11 | 12 | program -> init 13 | init --> program : fetchAll 14 | program -> MU : (model, PlayersMsg (FetchAllDone players)) 15 | MU -> PU : (currentPlayers, FetchAllDone players) 16 | PU --> MU : Updated players' collection 17 | MU --> program : Updated app model 18 | program -> MV : App model 19 | MV -> PL : Players 20 | PL --> MV :Rendered view 21 | MV --> program : Rendered view 22 | @enduml 23 | -------------------------------------------------------------------------------- /zh-TW/06-fetching-resources/02-players-messages.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # 玩家訊息 4 | 5 | 首先,建立用來擷取玩家的訊息。新增一個匯入及訊息到 __src/Players/Messages.elm__ 6 | 7 | ```elm 8 | module Players.Messages exposing (..) 9 | 10 | import Http 11 | import Players.Models exposing (PlayerId, Player) 12 | 13 | 14 | type Msg 15 | = OnFetchAll (Result Http.Error (List Player)) 16 | ``` 17 | 18 | `OnFetchAll` 當從伺服端取得回應時呼叫。附帶的 `Result` 可能會是 `Http.Error` 或者玩家列表。 -------------------------------------------------------------------------------- /zh-TW/06-fetching-resources/03-players-update.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # 玩家更新 4 | 5 | 當請求玩家完成後,將會觸發 `OnFetchAll` 訊息。 6 | 7 | __src/Players/Update.elm__ 處理這個新訊息。更改 `update` 成: 8 | 9 | ```elm 10 | ... 11 | update : Msg -> List Player -> ( List Player, Cmd Msg ) 12 | update message players = 13 | case message of 14 | OnFetchAll (Ok newPlayers) -> 15 | ( newPlayers, Cmd.none ) 16 | 17 | OnFetchAll (Err error) -> 18 | ( players, Cmd.none ) 19 | ``` 20 | 21 | 當收到 `OnFetchAll` 時使用樣式對應來決定要作什麼事。 22 | 23 | - `Ok` 情況下傳回擷取到的玩家,用來更新玩家集合。 24 | - `Err` 情況下傳回與先前相同的東西。(比較好的作法是顯示錯誤訊息給使用者,但為了此教學的簡單性,這裡暫時不會這樣處理) 25 | -------------------------------------------------------------------------------- /zh-TW/06-fetching-resources/05-main.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # 主程式 4 | 5 | ## 主模型 6 | 7 | 將 __src/Models.elm__ 檔案內,寫死的玩家清單刪除 8 | 9 | ```elm 10 | initialModel : Model 11 | initialModel = 12 | { players = [] 13 | } 14 | ``` 15 | 16 | ## 主程式 17 | 18 | 最後,希望應用程式啟動時執行 `fetchAll`。 19 | 20 | 更新 __src/Main.elm__: 21 | 22 | ```elm 23 | ... 24 | import Messages exposing (Msg(..)) 25 | ... 26 | import Players.Commands exposing (fetchAll) 27 | 28 | init : ( Model, Cmd Msg ) 29 | init = 30 | ( initialModel, Cmd.map PlayersMsg fetchAll ) 31 | ``` 32 | 33 | 現在,當應用程式啟動時,`init` 傳回命令列表。 34 | -------------------------------------------------------------------------------- /zh-TW/06-fetching-resources/06-try-it.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # 試試看 4 | 5 | 試試!在終端機下執行 API 伺服端: 6 | 7 | ```bash 8 | nf start 9 | ``` 10 | 11 | 重新整理瀏覽器,應用程式現在會從伺服端擷取玩家清單。應用程式看起來: 12 | 13 | ![Screenshot](screenshot.png) 14 | 15 | 你的應用程式原始碼在這個階段看起來像是: . 16 | -------------------------------------------------------------------------------- /zh-TW/06-fetching-resources/cover.md: -------------------------------------------------------------------------------- 1 | # 擷取資源 2 | 3 | 這個章節包含了從 API 擷取玩家集合。 4 | 5 | 截至目前為止,你的程式碼應該像是 6 | -------------------------------------------------------------------------------- /zh-TW/06-fetching-resources/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/zh-TW/06-fetching-resources/screenshot.png -------------------------------------------------------------------------------- /zh-TW/07-routing/01-intro.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # 簡介 4 | 5 | 讓我們加入路由到應用程式。使用 [Elm Navigation 包](http://package.elm-lang.org/packages/elm-lang/navigation/) 及 [UrlParser](http://package.elm-lang.org/packages/evancz/url-parser/)。 6 | 7 | - Navigation 提供了更改瀏覽器網址及對應的方法 8 | - UrlParser 提供路由比對器 9 | 10 | 首先安裝: 11 | 12 | ```bash 13 | elm package install elm-lang/navigation 14 | elm package install evancz/url-parser 15 | ``` 16 | 17 | `Navigation` 函式庫包裝 `Html.App`。包含了 `Html.App` 所有功能並額外加上: 18 | 19 | - 監聽瀏覽器網址的改變 20 | - 當網址改變時觸發訊息 21 | - 提供改變瀏覽器網址的方法 22 | 23 | ## 流程 24 | 25 | 用以下幾張圖表了解路由的運作。 26 | 27 | ### 初始轉譯 28 | 29 | ![流程](01-intro.png) 30 | 31 | - (1) 當第一次讀取 `Navigation` 模組,將會擷取目前的 `Location` 送到應用程式的 `init` 函式。 32 | - (2) 在 `init` 函式中剖析 location 並取得符合的 `Route`。 33 | - (3, 4) 接著將符合的 `Route` 儲存在初始模型,將初始模型傳回到 `Navigation`。 34 | - (5, 6) `Navigation` 使用初始模型來轉譯視界。 35 | 36 | ### 當網址改變 37 | 38 | ![流程](01-intro_001.png) 39 | 40 | - (1) 當瀏覽器網址改變時,Navigation 函式庫接收到事件 41 | - (2) 一個 `OnLocationChange` 訊息會送到 `update` 函式,此訊息包含新的網址 42 | - (3, 4) 在 `update` 中,剖析 `Location` 並傳回符合的 `Route` 43 | - (5) 從 `update` 傳回了更新後的模型,包含更新 `Route`。 44 | - (6, 7) Navigation 接著渲染應用程式 -------------------------------------------------------------------------------- /zh-TW/07-routing/01-intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/zh-TW/07-routing/01-intro.png -------------------------------------------------------------------------------- /zh-TW/07-routing/01-intro.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant Browser #white 6 | participant Navigation #white 7 | participant init #white 8 | participant update #white 9 | participant parseLocation #white 10 | participant View #white 11 | 12 | Navigation -> init : Current location 13 | init -> parseLocation : Location 14 | parseLocation --> init : Matched Route 15 | init --> Navigation : Initial model 16 | Navigation -> View : Model 17 | View --> Navigation : Rendered view 18 | 19 | newpage 20 | 21 | autonumber 1 "(#)" 22 | Browser -> Navigation : Location change event 23 | Navigation -> update : OnLocationChange 24 | update -> parseLocation : Location 25 | parseLocation --> update : Matched Route 26 | update --> Navigation : Updated model 27 | Navigation -> View : Model 28 | View --> Navigation : Rendered view 29 | 30 | @enduml 31 | 32 | -------------------------------------------------------------------------------- /zh-TW/07-routing/01-intro_001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/zh-TW/07-routing/01-intro_001.png -------------------------------------------------------------------------------- /zh-TW/07-routing/04-main-model.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # 主模型(Main model) 4 | 5 | 希望在主應用程式模型中儲存目前的路由。 6 | 更改 __src/Models.elm__ 成: 7 | 8 | ```elm 9 | module Models exposing (..) 10 | 11 | import Players.Models exposing (Player) 12 | import Routing 13 | 14 | 15 | type alias Model = 16 | { players : List Player 17 | , route : Routing.Route 18 | } 19 | 20 | 21 | initialModel : Routing.Route -> Model 22 | initialModel route = 23 | { players = [] 24 | , route = route 25 | } 26 | ``` 27 | 28 | 這裡: 29 | 30 | - 新增 `route` 到模型 31 | - 更改 `initialModel` 取得一個 `route` 32 | -------------------------------------------------------------------------------- /zh-TW/07-routing/05-main-messages.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # 主訊息(Main messages) 4 | 5 | 當瀏覽器網址改變時,觸發一個新訊息。 6 | 7 | 修改 __src/Messages.elm__ 成: 8 | 9 | ```elm 10 | module Messages exposing (..) 11 | 12 | import Navigation exposing (Location) 13 | import Players.Messages 14 | 15 | 16 | type Msg 17 | = PlayersMsg Players.Messages.Msg 18 | | OnLocationChange Location 19 | ``` 20 | 21 | - 現在引入 `Navigation` 22 | - 接著新增 `OnLocationChange Location` 訊息 -------------------------------------------------------------------------------- /zh-TW/07-routing/06-main-update.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # 主更新(Main update) 4 | 5 | 需要讓 `update` 函式回應 `OnLocationChange` 訊息。 6 | 7 | 在 __src/Update.elm__ 新增一個分支: 8 | 9 | ```elm 10 | ... 11 | import Routing exposing (parseLocation) 12 | 13 | ... 14 | 15 | update msg model = 16 | case msg of 17 | ... 18 | OnLocationChange location -> 19 | let 20 | newRoute = 21 | parseLocation location 22 | in 23 | ( { model | route = newRoute }, Cmd.none ) 24 | ``` 25 | 26 | 當收到 `OnLocationChange` 訊息,剖析此路徑並儲存符合的路由於模型。 -------------------------------------------------------------------------------- /zh-TW/07-routing/09-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/zh-TW/07-routing/09-edit.png -------------------------------------------------------------------------------- /zh-TW/07-routing/09-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/zh-TW/07-routing/09-list.png -------------------------------------------------------------------------------- /zh-TW/07-routing/09-try-it.md: -------------------------------------------------------------------------------- 1 | # 試試看 2 | 3 | 試試目前的進度。執行下列指令啟動應用程式: 4 | 5 | ```bash 6 | nf start 7 | ``` 8 | 9 | 接著開啟瀏覽器前往 `http://localhost:3000` 會看到玩家列表。 10 | 11 | ![screenshot](09-list.png) 12 | 13 | 如果前往 `http://localhost:3000/#players/2` 會看到一位玩家。 14 | 15 | ![screenshot](09-edit.png) 16 | 17 | 接下來將會新增一些導覽。 18 | 19 | 截至目前為止應用程式要看起來像是 . 20 | 21 | -------------------------------------------------------------------------------- /zh-TW/07-routing/cover.md: -------------------------------------------------------------------------------- 1 | # 路由(Routing) 2 | 3 | 本章節涵蓋在應用程式內新增路由。 4 | 5 | 截至目前為止,你的程式碼應該像是 6 | 7 | -------------------------------------------------------------------------------- /zh-TW/08-edit/01-plan.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # 規劃 4 | 5 | 更改某個玩家等級的計畫如下: 6 | 7 | ![Flow](01-plan.png) 8 | 9 | (1) 當使用者點擊增加或減少的按鈕,觸發 `ChangeLevel` 訊息並伴隨著 `playerId` 及 `howMuch`。 10 | 11 | (2) __Html.program__(由 Navigation 包裝 )將發送訊息回到 `Main.Update` 進而轉送到 `Players.Update` (3)。 12 | 13 | (4) `Players.Update` 將傳回命令來儲存玩家,此命令往上傳遞到 __Html.program__ (5)。 14 | 15 | (6) Elm 執行期執行命令(觸發 API 呼叫)並得到成功或失敗的結果。若成功將會觸發 `SaveSuccess` 訊息並伴隨著更新後的玩家。 16 | 17 | (7) `Main.Update` 路由 `SaveSuccess` 訊息至 `Players.Update`。 18 | 19 | (8) 在 `Players.Update` 中,更新 `players` 模型並傳回。流回到 Html.program (9)。 20 | 21 | (10) 接著 Html.program 使用更新後的模型渲染應用程式。 22 | -------------------------------------------------------------------------------- /zh-TW/08-edit/01-plan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/zh-TW/08-edit/01-plan.png -------------------------------------------------------------------------------- /zh-TW/08-edit/01-plan.pu: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | autonumber "(#)" 4 | 5 | participant Html.program as program #white 6 | participant Main.Update as MU #white 7 | participant Main.View as MV #white 8 | participant Players.Update as PU #white 9 | participant Players.Edit as PE #white 10 | 11 | PE -> program : PlayersMsg (ChangeLevel playerId howMuch) 12 | program -> MU : PlayersMsg (ChangeLevel playerId howMuch) 13 | MU -> PU : ChangeLevel playerId howMuch 14 | PU --> MU : Command to save 15 | MU --> program : Command to save 16 | ||| 17 | program -> MU : PlayersMsg (SaveSuccess player) 18 | MU -> PU : (SaveSuccess player) 19 | PU --> MU : Updated players 20 | MU --> program : Updated model 21 | program -> MV : Updated model 22 | 23 | 24 | @enduml 25 | 26 | -------------------------------------------------------------------------------- /zh-TW/08-edit/02-messages.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | # 玩家訊息(Messages) 4 | 5 | 開始加入需要的訊息。 6 | 7 | 在 __src/Players/Messages.elm__ 檔案新增: 8 | 9 | ```elm 10 | type Msg 11 | ... 12 | | ChangeLevel PlayerId Int 13 | | OnSave (Result Http.Error Player) 14 | ``` 15 | 16 | - 當使用者希望更改等級時,將會觸發 `ChangeLevel`。第二個參數為整數,指明更改多少等級,例如 -1 表示遞減, 1 表示遞增。 17 | - 接著,希望能夠發送更新玩家的請求至 API。當 API 回應時將會觸發 `OnSave`。 18 | - `OnSave` 將會是成功伴隨更新的玩家或者失敗的 Http 錯誤。 -------------------------------------------------------------------------------- /zh-TW/08-edit/03-player-edit.md: -------------------------------------------------------------------------------- 1 | > 本頁包含 Elm 0.18 2 | 3 | ## 玩家編輯(Player edit)視界 4 | 5 | 新增 `ChangeLevel` 訊息。從玩家編輯視界觸發這個訊息。 6 | 7 | 編輯 __src/Players/Edit.elm__ 檔案,修改 `btnLevelDecrease` 及 `btnLevelIncrease`: 8 | 9 | ```elm 10 | ... 11 | btnLevelDecrease : Player -> Html Msg 12 | btnLevelDecrease player = 13 | a [ class "btn ml1 h1", onClick (ChangeLevel player.id -1) ] 14 | [ i [ class "fa fa-minus-circle" ] [] ] 15 | 16 | 17 | btnLevelIncrease : Player -> Html Msg 18 | btnLevelIncrease player = 19 | a [ class "btn ml1 h1", onClick (ChangeLevel player.id 1) ] 20 | [ i [ class "fa fa-plus-circle" ] [] ] 21 | ``` 22 | 23 | 在這兩個按鈕新增 `onClick (ChangeLevel player.id howMuch)`。其中 `howMuch` 為 `-1` 來遞減等級,`1` 則是遞增。 24 | -------------------------------------------------------------------------------- /zh-TW/08-edit/cover.md: -------------------------------------------------------------------------------- 1 | # 編輯(Editing) 2 | 3 | 這是最終章節,我們將編輯玩家等級並儲存於後端。 4 | 5 | 截至目前為止,你的程式碼應該像是 . 6 | -------------------------------------------------------------------------------- /zh-TW/09-conclusion/01-improvements.md: -------------------------------------------------------------------------------- 1 | # 改進 2 | 3 | 下列為可能的改善清單,你可以用來改進這個應用程式。 4 | 5 | ## 新增及刪除玩家 6 | 7 | 我留下這個為了讓教學能夠短些,當然這是重要功能。 8 | 9 | ## 更改玩家名稱 10 | 11 | ## 當 Http 請求失敗顯示錯誤訊息 12 | 13 | 目前如果獲取或儲存玩家失敗,什麼事也沒作。如果能夠顯示錯誤訊息給使用者,那會更好些。 14 | 15 | ## 更甚至是更好的錯誤訊息 16 | 17 | 比單純顯示錯誤訊息更好的是: 18 | 19 | - 顯示不同類型的閃現(flash)訊息,例如,錯誤或提示 20 | - 一次顯示數個閃現訊息 21 | - 可以忽略訊息 22 | - 自動在數秒後移除訊息 23 | 24 | ## 樂觀的更新 25 | 26 | 目前所有的更新函式都是樂觀的。意思是,只有在伺服端成功回應訊息後,才會更改模型。一個重大的改良就是,應用程式能夠加入樂觀的新增、修改及刪除。這就表示更好的錯誤控制。 27 | 28 | ## 驗證 29 | 30 | 我們必須避免玩家沒有名稱。一個好的功能就是有玩家名稱的驗證,這樣就不會是空值。 31 | 32 | ## 新增津貼及紅利 33 | 34 | 我們可以新增一個玩家可以擁有的津貼列表。這些津貼有裝備、服裝、條幅(scrolls)、配件等等,例如,"銅劍"。接著,有玩家與津貼之間的關聯。 35 | 36 | 每一個津貼會關聯一個紅利。玩家將會計算出強度,強度為等級加上紅利。 37 | 38 | --- 39 | 40 | 有關此應用程式的特色版本,請見 的 master 分支。 41 | -------------------------------------------------------------------------------- /zh-TW/09-conclusion/cover.md: -------------------------------------------------------------------------------- 1 | # 結論 2 | 3 | 此章節為本教學的結論,有些改良或功能想法。 4 | 5 | 我希望能夠聽到你的回饋,改良這份教學。請開啟議題於 。 6 | 7 | 感謝! 8 | -------------------------------------------------------------------------------- /zh-TW/GLOSSARY.md: -------------------------------------------------------------------------------- 1 | functions 函式 2 | function signatures 函式標記式 3 | partial application 部份套用 4 | pipe operator 輸送運算子 5 | anonymous functions 匿名函式 6 | named functions 具名函式 7 | arguments 函式引數 8 | union types 聯集型別 9 | type aliases 型別別名 10 | record 紀錄 11 | definition 定義式 12 | constructor 建構式 13 | the unit type 單位型別 14 | task 任務 15 | model 模型 16 | state 狀態 17 | message 訊息 18 | view 視界 19 | render 轉譯 20 | subscription 訂閱 21 | update 更新 22 | pattern matching 樣式對應 23 | composing 組成 24 | emit 發出 25 | parameterized types 參數化型別 26 | -------------------------------------------------------------------------------- /zh-TW/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sporto/elm-tutorial/884b8200fd977b243bad3d190919ded5b5d53389/zh-TW/logo.png -------------------------------------------------------------------------------- /zh-TW/tips-tricks/context.md: -------------------------------------------------------------------------------- 1 | # Contexts 2 | 3 | 典型的 `update` 或 `view` 函式看起來像似: 4 | 5 | ```elm 6 | view : Model -> Html Msg 7 | view model = 8 | ... 9 | ``` 10 | 11 | 或者 12 | 13 | ```elm 14 | update : Msg -> Model -> (Model, Cmd Msg) 15 | update message model = 16 | ... 17 | ``` 18 | 19 | 這在思考上很容易走不過去,你只需要傳遞屬於該元件的 `Model`。有時候你需要額外的資訊且這是很正常的事情。舉例來說: 20 | 21 | ```elm 22 | type alias Context = 23 | { model : Model 24 | , time : Time 25 | } 26 | 27 | view : Context -> Html Msg 28 | view context = 29 | ... 30 | ``` 31 | 32 | 這個函式需要元件的模型外加 `time`,這個定義在他的父模型中。 33 | -------------------------------------------------------------------------------- /zh-TW/tips-tricks/point-free-style.md: -------------------------------------------------------------------------------- 1 | # Point free 風格 2 | 3 | Point free 是一種撰寫函式的風格,此風格忽略內部一個或多個函數引述。透過範例來稍作了解。 4 | 5 | 這裡有個程式,對某個數值額外加上 10: 6 | 7 | ```elm 8 | add10 : Int -> Int 9 | add10 x = 10 | 10 + x 11 | ``` 12 | 13 | 可以使用 `+` 前墜標記法來改寫: 14 | 15 | ```elm 16 | add10 : Int -> Int 17 | add10 x = 18 | (+) 10 x 19 | ``` 20 | 21 | 此例的函式引數 `x` 並非完全必要,可以改寫成: 22 | 23 | ```elm 24 | add10 : Int -> Int 25 | add10 = 26 | (+) 10 27 | ``` 28 | 29 | 注意到函式引數的 `x` 以及 `+` 旁邊的 `x` 都消失了。`add10` 仍然是個函式,需要一個整數來計算結果。這樣的省略引數稱之為__point free 風格__。 30 | 31 | ## 更多範例 32 | 33 | ```elm 34 | select : Int -> List Int -> List Int 35 | select num list = 36 | List.filter (\x -> x < num) list 37 | 38 | select 4 [1, 2, 3, 4, 5] == [1, 2, 3] 39 | ``` 40 | 41 | 相同於: 42 | 43 | ```elm 44 | select : Int -> List Int -> List Int 45 | select num = 46 | List.filter (\x -> x < num) 47 | 48 | select 4 [1, 2, 3, 4, 5] == [1, 2, 3] 49 | ``` 50 | 51 | --- 52 | 53 | ```elm 54 | process : List Int -> List Int 55 | process list = 56 | reverse list |> drop 3 57 | ``` 58 | 59 | 相同於: 60 | 61 | ```elm 62 | process : List Int -> List Int 63 | process = 64 | reverse >> drop 3 65 | ``` 66 | 67 | -------------------------------------------------------------------------------- /zh-TW/tips-tricks/troubleshooting.md: -------------------------------------------------------------------------------- 1 | # 故障檢修 2 | 3 | 如果你在開發過程中遇到某些奇怪的編譯行為,試著刪除 `elm-stuff/build-artifacts` 並再次編譯,這通常會解決一些問題。 4 | --------------------------------------------------------------------------------