Mateusz Pokora
vs.
todos =
[ "Learn elm"
, "Eat pizza"
, "Have fun"
]
import Html as H
import Html.Attributes as A
H.div [A.class "title"] [
H.span [] [H.text "Hello"]
]
// Deklaracja funkcji
sayHello : String -> String
sayHello name =
"Hello " ++ name ++ "!"
// Wywołanie
sayHello "Mateusz"
todos =
[ "Learn elm"
, "Eat pizza"
, "Have fun"
]
List.map
List.filter
List.concat
List.map
(\todo ->
H.div [] [ H.text todo.title ]
)
/* point2D : { x : Int , y : Int } */
point2D =
{ x = 0
, y = 0
}
type alias Point2D =
{ x : Int
, y : Int
}
point : Point2D
point =
{ x = 0
, y = 0
}
var user = {
name: "Mateusz",
age: 21
};
user.age = 100;
Nie modyfikujemy istniejących struktur. Zamiast tego tworzymy nowe aktualizując pola.
user : User
user = {
name = "Mateusz"
, age = 21
}
updatedUser = {
user | age = 100
}
Text
https://elmbridge.github.io/curriculum/images/elm-architecture-1.jpeg
type alias Model = {
nameInput : String
, emailInput : String
, termsAndConditionsInput : Bool
, formValid : Bool
, modalOpen : Bool
}
view : Model -> Html Msg
view model =
div [] [
input [
value model.emailInput
, onClick UpdateEmail
]
[]
]
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
UpdateEmail email ->
({ model | email = email}, Cmd.none )
SubmitForm ->
// komunikacja z serwerem
Html.program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
Funkcja opisująca jak wygląda nasza aplikacja
1. npm install -g elm elm-format create-elm-app
2. create-elm-app todoApp
3. cd ./todoApp
4. elm-app start
1. git checkout
https://github.com/pokorson/node-workshop-server
2. install atom packages
elm-jutsu
linter
linter-elm-make
elm-language
type alias Model =
{ todoList : List Todo
}
type alias Todo =
{ title : String
, id : Int
}
type Msg = NoOp
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
(model, Cmd.none)
view : Model -> H.Html Msg
view model =
H.div [] [...]
type alias Todo =
{ title : String
, id : Int
, completed : Bool
}
H.div [] [
if todo.completed then
H.text "Completed"
else
H.text "In progress"
]
if (age == 21) {
return 0;
} else {
// do something
}
db.saveUser()
H.div [] [
if todo.completed then
H.text "Completed"
else
H.text "In progress"
]
H.div -> List Attribute -> ...
// dodaj opcjonalną klase
H.button [ A.type_ "submit" ]
Jak dodać opcjonalny atrybut do elementu?
type Msg
= ToggleCompleted Int
| DoSomethingElse
Typy pozwalające lepiej odzwierciedlić co się dzieje w naszym kodzie
filter = "0"
if (filter == "0") {
return "aktywny";
} else if (filter == "1") {
return "nieaktywny";
}
type Filter = Active | NonActive
case value of
[] ->
// pusta lista
head :: [] ->
// Lista jednoelementowa
head :: tail ->
// Lista wieloelementowa
Kompilator sprawdza czy obsługujemy wszystkie możliwości danego typu
type Visibility =
All
| Active
| Completed
tableView : Visibility -> Html Msg
tableView visibility =
div [] [
case visibility of
All ->
text "Wszystkie"
Active ->
text "Aktywne"
]
This `case` does not have branches for all possibilities.
90|> case visibility of
91|> All ->
92|> text "Wszystkie"
93|>
94|> Active ->
95|> text "Aktywne"
You need to account for the following values:
Main.Completed
Add a branch to cover this pattern!
todoItem todo =
H.div [
E.onClick (ToggleCompleted todo.id)
] [...]
type alias Model =
{ ...
, visibility : Filter
}
type Filter
= All
| Completed
| Uncompleted
type Msg =
...
| ToggleFilter Filter
update msg model =
case msg of
ToggleFilter filter ->
...
List.map
(\todo -> H.text todo.title)
(List.filter (\todo -> todo.completed) model.todoList)
// pipe operator
// przekazujemy wartość do funkcji
model.todoList
|> List.filter (\todo -> todo.completed)
|> List.map (\todo -> H.text todo.title)
description : Maybe String
description =
Just "I'm description"
description =
Nothing
case description of
Just body ->
String.reverse body
Nothing ->
""
import TodoList
type alias Model =
{ todoList : TodoList.Model
}
import TodoList
view : Msg -> Model -> H.Html Msg
view msg model =
H.div []
[ H.button [ A.onClick DoSomething ] []
, TodoList.view model.todoList
]
type Msg = DoSomething
import TodoList
view : Msg -> Model -> H.Html Msg
view msg model =
H.div []
[ H.button [ A.onClick DoSomething ] []
, H.map TodoListMsg (TodoList.view model.todoList)
]
type Msg
= DoSomething
| TodoListMsg TodoList.Msg
TodoListMsg listMsg ->
let
( newListModel, newListMsg ) =
TodoList.update listMsg model.todoList
in
( { model | todoList = newListModel }, Cmd.map TodoListMsg newListMsg )
elm-package install NoRedInk/elm-decode-pipeline
todosRequest : Request a
todosRequest =
Http.get "http://localhost:3030/todos" decoder
todoDecoder : Decode.Decoder Todo
todoDecoder =
DecodeP.decode Todo
|> DecodeP.required "title" Decode.string
|> DecodeP.required "id" Decode.int
init : ( Model, Cmd Msg )
init =
( ...
, Http.send TodoListLoaded fetchTodos
)
update msg model =
case msg of
FetchTodos ->
(model
, Http.send TodoListLoaded fetchTodos)
...
type alias RemoteModel =
{ todoList : List Todo
, requestPending : Bool
, requestError : String
}
Utworzenie struktury modelu w taki sposób aby wykluczyć stany które wzajemnie się wykluczają
type ListState
= Loading
| Failure String
| Success (List Todo)
type alias Model =
{ todoList : ListState
, visibility : Filter
}
type ListState
= Loading
| Failure String
| Success (List Todo)
view model =
case model.todoList of
Loading ->
H.text "todo list loading..."
Failure err ->
H.text "error"
Success todoList ->
renderList...