Elm 0.18로 만드는 Todo 앱 (5)
10795 단어 Elm
Elm 0.18로 만드는 Todo 앱(1) 「고정치의Todo를Todo리스트에 추가할 수 있게 한다」
Elm 0.18로 만드는 Todo 앱 (2) “텍스트 박스에 입력한 Todo를 Todo 목록에 추가할 수 있도록 한다”
Elm 0.18로 만드는 Todo 앱 (3) “Todo 확인을 위해 체크박스 설치하기”
Elm 0.18로 만드는 Todo 앱 (4) 「TodoList측의 기능 확장을 한다.」
마지막으로 토도 앱을 확장합니다.
이번 테마
(최종회) 일의로 update 하는Todo를 결정할 수 있도록 기능확장한다.
파일 구성
구현
Todo.elm 수정
type alias Model =
- { done : Bool
+ { itemID : Int
+ , done : Bool
, item : String
, del : Bool
}
-new : Bool -> String -> Bool -> Model
-new do s de =
- { done = do
+new : Int -> Bool -> String -> Bool -> Model
+new itemID do s de =
+ { itemID = itemID
+ , done = do
, item = s
, del = de
}
type Msg
= NoOp
- | ToggleDone String
- | OnDelete String
+ | ToggleDone Int
+ | OnDelete Int
Todo를 고유하게 식별하기 위해 itemID 속성을 추가합니다.
이에 따라 new 함수의 인수나 메시지도 수정합니다.
update : Msg -> Model -> Model
update message model =
case message of
NoOp ->
model
- ToggleDone s ->
- if s == model.item then
+ ToggleDone itemID ->
+ if itemID == model.itemID then
{ model | done = not model.done }
else
model
- OnDelete s ->
- if s == model.item then
+ OnDelete itemID ->
+ if itemID == model.itemID then
{ model | del = True }
else
model
ToggleDone과 onDelete의 인수를 문자열에서 itemID로 변경하고, itemID 단위로 해당하는 Todo만 상태를 변경하게 하고 있습니다.
view : Model -> Html Msg
view model =
li []
[
- checkbox (ToggleDone model.item) model
+ checkbox (ToggleDone model.itemID) model
]
checkbox : Msg -> Model -> Html Msg
checkbox msg model =
label []
[ input [ type_ "checkbox", checked model.done, onClick msg ] []
, viewItem model
, viewDeleteButton model
]
viewItem : Model -> Html Msg
viewItem model =
if model.done == False then
text model.item
else
s []
[ span [ style [ ("color", "gray") ] ]
[ text model.item ]
]
viewDeleteButton : Model -> Html Msg
viewDeleteButton model =
span []
- [ button [ onClick (OnDelete model.item) ] [ text "x" ]
+ [ button [ onClick (OnDelete model.itemID) ] [ text "x" ]
]
메시지의 정의 변경에 맞게 인수를 itemID로 변경하고 있습니다.
TodoList.elm 변경
module TodoList exposing (..)
import Html exposing (..)
import Html.Attributes exposing (class)
import Html.Events exposing (onClick)
import Todo
type alias Model =
{ todoList : List TodoModel
+ , nextID : Int
}
initialModel : Model
initialModel =
{ todoList =
- [ Todo.new False "task1" False
- , Todo.new False "task2" False
- , Todo.new True "task3" False
- , Todo.new False "task4" False
+ [ Todo.new 1 False "task1" False
+ , Todo.new 2 False "task2" False
+ , Todo.new 3 True "task3" False
+ , Todo.new 4 False "task4" False
]
+ , nextID = 5
}
type Msg
= NoOp
| AddNew
| DeleteFinished
| TodoMsg Todo.Msg
-- update
-update : Msg -> TodoModel -> Model -> ( Model, Cmd Msg )
-update message todo model =
+update : Msg -> String -> Model -> ( Model, Cmd Msg )
+update message item model =
case message of
NoOp ->
model ! []
AddNew ->
- { model | todoList = model.todoList ++ [todo] } ! []
+ let
+ todo =
+ Todo.new model.nextID False item False
+ in
+ { model |
+ todoList = model.todoList ++ [todo]
+ , nextID = model.nextID + 1
+ } ! []
DeleteFinished ->
let
itemIsNotFinished todoModel = not todoModel.done
in
{ model |
todoList = List.filter itemIsNotFinished model.todoList } ! []
TodoMsg subMsg ->
let
itemIsNotDeleted todoModel =
not todoModel.del
updatedTodoList =
List.map (Todo.update subMsg) model.todoList
in
{ model |
todoList = List.filter itemIsNotDeleted updatedTodoList } ! []
-- view
view : Model -> Html Msg
view model =
div []
[
div [ class "p2" ]
[ addButton
, viewCounter model
, deleteFinishedButton
, viewList model
]
]
addButton : Html Msg
addButton =
div []
[ button [ onClick AddNew ] [ text "Add" ] ]
deleteFinishedButton : Html Msg
deleteFinishedButton =
div []
[ button [ onClick DeleteFinished ] [ text "Delete Finished" ] ]
viewCounter : Model -> Html Msg
viewCounter model =
div []
[ text ("Finished Task: "
++ toString ( countDoneItems model )
++ "/"
++ toString ( List.length model.todoList ) )
]
countDoneItems : Model -> Int
countDoneItems model =
List.filter itemIsDone model.todoList
|> List.length
itemIsDone : TodoModel -> Bool
itemIsDone todoModel = todoModel.done
viewList : Model -> Html Msg
viewList model =
(ul []
(List.map Todo.view model.todoList))
|> Html.map TodoMsg
모델에 nextID 속성 (다음의 Tot의 ID)을 추가하고 있습니다.
다른 수정 사항은 Todo.elm의 모델 변경과 관련이 있습니다.
update의 인수의 형태를 일부 변경했습니다.
TodoModel 형을 String 형으로 변경한 것으로, AddNew 의 코드의 전망이 나빠졌기 때문에, let-in문으로 재작성했습니다. nextID 증분 처리를 추가하고 있습니다.
Main.elm 변경
module Main exposing (..)
-import Html exposing (Html, program)
+import Html exposing (..)
import TodoCreator
import TodoList
-import Todo
main : Program Never Model Msg
main =
program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- model
type alias Model =
{ todoCreator : TodoCreator.Model
, todoList : TodoList.Model
}
initialModel : Model
initialModel =
{ todoCreator = TodoCreator.initialModel
, todoList = TodoList.initialModel
}
init : ( Model, Cmd Msg)
init =
( initialModel, Cmd.none)
type Msg
= TodoCreatorMsg TodoCreator.Msg
| TodoListMsg TodoList.Msg
-- update
update : Msg -> Model -> ( Model, Cmd Msg )
update message model =
case message of
TodoCreatorMsg subMsg ->
let
( updatedCreator, todoCreatorCmd ) =
TodoCreator.update subMsg model.todoCreator
in
( { model | todoCreator = updatedCreator }, Cmd.map TodoCreatorMsg todoCreatorCmd )
TodoListMsg subMsg ->
let
( updatedTodoListModel, todoListCmd ) =
- TodoList.update subMsg (Todo.new False model.todoCreator.inputStr False) model.todoList
+ TodoList.update subMsg model.todoCreator.inputStr model.todoList
in
( { model | todoList = updatedTodoListModel }, Cmd.map TodoListMsg todoListCmd )
-- subscription
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
-- view
view : Model -> Html Msg
view model =
- Html.div []
- [ Html.map TodoCreatorMsg (TodoCreator.view model.todoCreator)
- , Html.map TodoListMsg (TodoList.view model.todoList)
- ]
+ body []
+ [ h1 [] [ text "ToDo list" ]
+ , div []
+ [ map TodoCreatorMsg (TodoCreator.view model.todoCreator)
+ , map TodoListMsg (TodoList.view model.todoList)
+ ]
+ ]
TodoList의 메세지의 인수의 형태가 TodoModel형으로부터 String형으로 변경되었으므로,TodoList.update의 인수는 todoCreator의 inputStr를 그대로 건네줄 수가 있게 되었습니다.
그 결과, Todo를 import하지 않고 끝나게 되어,Todo의 변경에 영향을 받지 않게 되었습니다.
보기의 변경은 주로 보기 좋은 변화뿐입니다.
실행 결과
이전과 마찬가지로 make하고 만든 index.html을 브라우저에서 봅니다.
$ elm-make Main.elm --output index.html --debug
이번에는 내부 실장 변경이 주였기 때문에, 외형은 그다지 변하지 않습니다.
결론
5회에 걸쳐 연재해 온 Elm 0.18로 만드는 Todo 앱입니다만, 이번이 최종회입니다.
elm에 처음 만져 tutorial 등을 참고로 작성해 보았습니다.
Add 버튼이 TodoList 측에 있는 곳(가능하면 TodoCreator 측에 버튼 설치하고 싶다) 등 설계 우려가 되는 곳은 있습니다만, JavaScript를 건드리지 않고 여기까지 만들 수 있는 것은 대단하다고 생각했습니다.
Elm은 자바스크립트와 연동시킬 수 있는 것 같습니다만, 거기까지 손이 돌지 않았기 때문에, 서서히 공부해 나가고 싶습니다.
Reference
이 문제에 관하여(Elm 0.18로 만드는 Todo 앱 (5)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/tomluck/items/c3069bb66e6239217179
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
$ elm-make Main.elm --output index.html --debug
5회에 걸쳐 연재해 온 Elm 0.18로 만드는 Todo 앱입니다만, 이번이 최종회입니다.
elm에 처음 만져 tutorial 등을 참고로 작성해 보았습니다.
Add 버튼이 TodoList 측에 있는 곳(가능하면 TodoCreator 측에 버튼 설치하고 싶다) 등 설계 우려가 되는 곳은 있습니다만, JavaScript를 건드리지 않고 여기까지 만들 수 있는 것은 대단하다고 생각했습니다.
Elm은 자바스크립트와 연동시킬 수 있는 것 같습니다만, 거기까지 손이 돌지 않았기 때문에, 서서히 공부해 나가고 싶습니다.
Reference
이 문제에 관하여(Elm 0.18로 만드는 Todo 앱 (5)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/tomluck/items/c3069bb66e6239217179텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)