Go로 TodoList 만들기(2)

김영한·2021년 3월 18일
0

Go로 TodoList 만들기

목록 보기
2/2

참고
Github

📚 POST로 리스트 추가하기

app.go

...
func addTodoHandler(w http.ResponseWriter, r *http.Request) { // 프론트에서 올 때 name에다 Item을 넣어서 온다.
	name := r.FormValue("name") // 키를 통해서 value에 있는 Item을 꺼낸다.
	id := len(todoMap) + 1      // 임의의 ID
	todo := &Todo{id, name, false, time.Now()}
	todoMap[id] = todo
	// 렌더링을 사용해서 JSON으로 반환
	rd.JSON(w, http.StatusOK, todo)
}
...
func MakeHandler() http.Handler {
...
	r.HandleFunc("/todos", addTodoHandler).Methods("POST")
...
}

GET과 같은 todos 경로에 POST로 요청이오면 addTodoHandler로 간다.
addTodoHandler에서는 name 키에 있는 value를 꺼내서 todoMap에 추가해주고 render를 사용해서 JSON으로 변환해 응답해준다.

todo.js

...
        $('.todo-list-add-btn').on("click", function(event) {
            event.preventDefault();
    
            var item = $(this).prevAll('.todo-list-input').val();
    
            if (item) {
                $.post("/todos", {name:item}, addItem) // 리스트를 입력하고 버튼을 누르면 todos 서버에 name에 item을 넣어서 post로 보내고 응답이 오면 addItem을 호출해서 화면에 추가
                
                //todoListItem.append("<li><div class='form-check'><label class='form-check-label'><input class='checkbox' type='checkbox' />" + item + "<i class='input-helper'></i></label></div><i class='remove mdi mdi-close-circle-outline'></i></li>"); -> 서버에 보내지않고 그냥 바로 add
                todoListInput.val("");
            }
        });

        var addItem = function(item) {
            if (item.completed) { // item.id가 있어야 remove요청을 할 수 있으므로 추가
                todoListItem.append("<li class='completed'"+ " id = '" + item.id + "'><div class='form-check'><label class='form-check-label'><input class='checkbox' type='checkbox' checked='checked' />" + item.name + "<i class='input-helper'></i></label></div><i class='remove mdi mdi-close-circle-outline'></i></li>");
            } else {
                todoListItem.append("<li "+ " id = '" + item.id + "'><div class='form-check'><label class='form-check-label'><input class='checkbox' type='checkbox' />" + item.name + "<i class='input-helper'></i></label></div><i class='remove mdi mdi-close-circle-outline'></i></li>");
            }
        };
...

프론트에서는 리스트를 입력하고 버튼을 누르면 item에 입력값이 저장되는데 name에 item값을 넣어서 todos 경로에 POST 메소드로 요청한다.
응답이 오면 addItem을 호출해서 화면에 나타내준다.

📚 ajax의 DELETE로 리스트 삭제하기

app.go

...
func removeTodoHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r) // mux.Vars를 통해 변수 맵을 만들어 검색
	id, _ := strconv.Atoi(vars["id"]) // id에 있는 문자열을 숫자로 변경
	if _, ok := todoMap[id]; ok {     // todoMap에 id가 있으면
		delete(todoMap, id) // 삭제하고
		rd.JSON(w, http.StatusOK, Success{true})
	} else {
		rd.JSON(w, http.StatusOK, Success{false})
	}
}

type Success struct {
	Success bool `json:"success"`
}
...
func MakeHandler() http.Handler {
...
	r.HandleFunc("/todos/{id:[0-9]+}", removeTodoHandler).Methods("DELETE") // 아이디는 1개 이상인 숫자로만 이루어짐
...
}


경로에 변수가 있을 경우 {name} 또는 {name:pattern} 형식을 사용하여 정의하고 mux.Vars를 통해 변수 맵을 만들어 검색할 수 있다.

todo.js

        todoListItem.on('click', '.remove', function() {
            // 서버로 요청을 날린다음에 요청이 처리된 다음 지워야한다.
            // url: todos/id, method: DELETE
            var id = $(this).closest("li").attr('id') // 가장 가까운 li 태그의 id를 가져온다.
            var $self = $(this);
            $.ajax({
                url: "todos/" + id,
                type: "DELETE",
                success: function(data) {
                    if (data.success) {
                        $self.parent().remove(); // 응답이 성공적으로 오면 지워준다.
                    }
                }
            })
            // $(this).parent().remove(); -> 바로 지워짐
        });

todos/id 경로에 DELETE 메소드로 요청한다.
success 응답이 오면 응답 중 success가 true일 때 id에 해당하는 리스트를 삭제해준다.

📚 GET을 이용해 토글박스 다루기

app.go

...
func completeTodoHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)                           // mux.Vars를 통해 변수 맵을 만들어 검색
	id, _ := strconv.Atoi(vars["id"])             // id에 있는 문자열을 숫자로 변경
	complete := r.FormValue("complete") == "true" // complete에 true가 담겨오면 체크하라는 뜻이고, false면 체크를 해제하라는 뜻
	if todo, ok := todoMap[id]; ok {
		todo.Completed = complete // true면 체크, false면 해제
		rd.JSON(w, http.StatusOK, Success{true})
	} else {
		rd.JSON(w, http.StatusOK, Success{false})
	}
}
...
func MakeHandler() http.Handler {
...
	r.HandleFunc("/complete-todo/{id:[0-9]+}", completeTodoHandler).Methods("GET")
...
}

앞에서 쓰인 Vars와 FormValue를 통해서 id와 토글박스 체크 여부를 알려주는 complete를 가져온다.
id가 todoMap에 존재하면 해당 id의 토글박스를 의미하는 Completed 변수에 해제하는지 체크하는지를 설정해주고 Success응답을 보내준다.

todo.js

...
        todoListItem.on('change', '.checkbox', function() {
            var id = $(this).closest("li").attr('id') // 가장 가까운 li 태그의 id를 가져온다.
            var $self = $(this);
            var complete = true;
            if ($(this).attr('checked')) { // 이미 체크되어있으면 false로 변경해준다.
                complete = false;
            }
            // 이미 체크되어있는 상태면 해제시키라는 의미에서 false를 날려주고, 해제되어 있는 상태면 체크하라는 의미에서 true를 날려준다.
            $.get("complete-todo/"+id+"?complete="+complete, function(data) { // 체크되어있는지 아닌지에 따라 다른 응답이 온다.
                if (complete) {
                    $self.attr('checked', 'checked');
                } else {
                    $self.removeAttr('checked');
                }
                $self.closest("li").toggleClass('completed');

                /* -> 서버에 날리지않고 그냥 체크되고 해제됨
                if ($self.attr('checked')) {
                    $self.removeAttr('checked');
                } else {
                    $self.attr('checked', 'checked');
                }
        
                $(this).closest("li").toggleClass('completed');
                */
            })
        });
...

complete변수에 현재 토글박스의 체크 유무를 알려주는 변수를 넣고 id와 complete를 포함한 경로에 GET으로 요청한다.
응답온 데이터는 상관하지말고 complete에 따라 토글박스를 설정해 화면에 나타내준다.


이렇게 해서 간단한 TodoList를 Bootstrap과 Go언어를 사용해서 만들어보았다.

0개의 댓글