Elm 0.18로 만드는 Todo 앱 (3)

12384 단어 Elm
지금까지의 복습

Elm 0.18로 만드는 Todo 앱(1) 「고정치의Todo를Todo리스트에 추가할 수 있게 한다」
Elm 0.18로 만드는 Todo 앱 (2) “텍스트 박스에 입력한 Todo를 Todo 목록에 추가할 수 있도록 한다”

마지막으로 토도 앱을 확장합니다.

이번 테마



Todo 점검을 위해 체크박스 설치

파일 구성


  • Main.elm : 대원의 프로그램. 기본적으로는 부하의 모듈에 위양할 뿐.
  • TodoList.elm : Todo 목록 관리하기
  • TodoCreator.elm : (이번에는 변경 없음) 텍스트 박스를 관리한다.
  • Todo.elm : (New!) 하나의 Todo를 관리한다.

  • 지금까지는 하나의 Todo가 단순한 문자열이었지만 체크 박스 추가와 같은 하나의 Todo에 대한 기능 추가가 가능합니다.
    그래서 관리하기 쉽도록 TodoList에서 Todo를 잘라내기로 결정했습니다.

    구현



    Todo.elm 새로 만들기


  • module 선언 및 import 관련
  • module Todo exposing (..)
    
    import Html exposing (..)
    import Html.Attributes exposing (style, type_, checked)
    import Html.Events exposing (onClick)
    
    
  • 모델 정의

  • 기본적으로 TodoList에서 잘라내지만 외부에서 임의의 Todo를 만들 수 있도록 initialModel 대신 new 함수를 새로 만들었습니다.
    확인란 처리를 위해 ToggleDone이라는 메시지를 정의합니다.
    -- model
    type alias Model = 
        { done : Bool
        , item : String
        }
    
    new : Bool -> String -> Model
    new b s = 
        { done = b
        , item = s
        }
    
    type Msg
        = NoOp
        | ToggleDone String
    
  • update 정의
  • -- update
    update : Msg -> Model -> Model
    update message model =
        case message of
            NoOp ->
                model
    
            ToggleDone s -> 
                if s == model.item then
                    { model | done = not model.done }
                else
                    model
    

    ToggleDone의 인수로 Todo 상당의 문자열을 받고, 해당의 Todo만 상태를 변경하게 하고 있습니다.
  • view 정의
  • -- view
    view : Model -> Html Msg
    view model = 
        li [] 
            [ 
                checkbox (ToggleDone model.item) model
            ]
    
    checkbox : msg -> Model -> Html msg
    checkbox msg model = 
        label []
            [ input [ type_ "checkbox", checked model.done, onClick msg ] []
            , viewItem model
            ]
    
    viewItem : Model -> Html msg
    viewItem model =
        if model.done == False then
            text model.item
        else
            s [] 
                [ span [ style [ ("color", "gray") ] ]
                        [ text model.item ]
                ]
    

    확인란을 처리하는 checkbox 함수를 정의합니다.
    checked 속성에 model.done을 설정하여 체크 상태가 변경되도록했습니다.
    viewItem은 마지막 TodoList의 viewItem에서 변경했으며 done의 상태에 따라 모양을 바꿉니다.

    TodoList.elm 변경


  • 전체 파일
  •  module TodoList exposing (..)
    
     import Html exposing (..)
     import Html.Attributes exposing (class)
     import Html.Events exposing (onClick)
    +import Todo
    
     -- model
    -type alias ToDo = 
    -    { done : Bool
    -    , item : String
    -    }
    +type alias TodoModel = Todo.Model
    
     type alias Model = 
    -    { todoList : List ToDo
    +    { todoList : List TodoModel
         }
    
     initialModel : Model
     initialModel = 
         { todoList = 
    -        [ ToDo False "item1" 
    -        , ToDo False "item2"
    -        , ToDo False "item3"
    +        [ Todo.new False "task1"
    +        , Todo.new False "task2"
    +        , Todo.new True "task3"
    +        , Todo.new False "task4"
             ]
         }
    
     type Msg
         = NoOp
         | AddNew
    +    | TodoMsg Todo.Msg
    
     -- update
    -update : Msg -> ToDo -> Model -> ( Model, Cmd Msg )
    +update : Msg -> TodoModel -> Model -> ( Model, Cmd Msg )
     update message todo model =
         case message of
             NoOp ->
                 model ! []
             AddNew -> 
                 { model | todoList = model.todoList ++ [todo] } ! []
    
    +        TodoMsg subMsg ->
    +            let
    +                updatedTodoList = 
    +                    List.map (Todo.update subMsg) model.todoList
    +            in
    +                { model | todoList = updatedTodoList } ! []
    +
     -- view
     view : Model -> Html Msg
     view model = 
         div []
             [
             div [ class "p2" ]
                 [ addButton
    -            , viewItems model.todoList
    +            , viewList model
                 ]
             ]
    
     addButton : Html Msg 
     addButton =
         div [] 
             [ button [ onClick AddNew ] [ text "Add" ] ]
    
    -viewItems : List ToDo -> Html Msg
    -viewItems models = 
    -    ul [] (List.map viewItem models)
    -
    -viewItem : ToDo -> Html Msg
    -viewItem model = 
    -    li [] [
    -        text model.item
    -    ]
    +viewList : Model -> Html Msg
    +viewList model = 
    +    (ul [] 
    +        (List.map Todo.view model.todoList))
    +        |> Html.map TodoMsg
    

    initialModel의 초기치 변경 이외는, 기본적으로Todo의 잘라내기에 의한 수정입니다.
    Todo에서 처리해야 할 것은 Todo.elm에 위양하고 있습니다.

    Main.elm 변경


  • 전체 파일
  •  module Main exposing (..)
    
     import Html exposing (Html, program)
     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 (TodoList.ToDo False model.todoCreator.inputStr) model.todoList
    +                    TodoList.update subMsg (Todo.new False model.todoCreator.inputStr) model.todoList
                 in
                     ( { model | todoList = updatedTodoListModel }, Cmd.map TodoListMsg todoListCmd )
    
    

    이쪽도 기본적으로Todo의 잘라내기에 의한 수정입니다.

    실행 결과



    이전과 마찬가지로 make하고 만든 index.html을 브라우저에서 봅니다.
    $ elm-make Main.elm --output index.html --debug
    

    체크 박스가 추가되어 체크하면 문자의 디자인이 변화하는 것을 알 수 있다고 생각합니다.


    결론



    Todo를 요소로 잘라내고, 그에 따른 변경과 체크박스를 추가해 왔습니다.

    다음 번에는 TodoList 측의 기능 확장 (Todo 완료 수 표시 등)을 실시하고 싶습니다.
    다음 번 : Elm 0.18로 만드는 Todo 앱(4)

    좋은 웹페이지 즐겨찾기