일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- grid-row-start
- gird-row-end
- package.json
- scope
- className
- grid-column-start
- grid-column-end
- react-hook-form
- border-style
- classList
- javascript
- prompt()
- localStorage
- collapsing-margins
- variables
- css#cascading#display#block#inline
- CSS
- relative
- javascipt
- createElement
- box-shadow
- grid-template-areas
- React
- python #qqplot #qq-plot #code
- foreach()
- valuable
- mongodb
- confirm()
- var
- Grid
- Today
- Total
data life
[JavaScript] CRUD 기능 구현 본문
json-server 란?
사실 우리가 무엇인가 개발하기 위해서는 백엔드의 구현이 필요합니다. 프론트엔드 개발자들에게 있어서 직접 백엔드 기능을 구현하는 것은 상당한 시간이 걸리기 때문에 짧은 시간에 가짜 API 서버를 구축해줄 도구인 json-sever를 이용해보도록 하겠습니다.
npm을 통해 설치 가능하며 이름과 같이 json 파일 하나로 연습용 서버를 쉽게 구성 할 수 있으나 실제 프로덕션에서 사용하지는 않기 때문에 이 서버를 이용해서 실제 프로젝트를 개발 하면 안된다는 점!!! 유의바랍니다.
실제 프로젝트 개발 시에는 백엔드 공부를 통해 서버를 직접 준비하거나 Firebase 를 사용해서 구현을 하도록 합시다!
json-server 설치
npm install -g json-server
db.json 생성
{
"todos": [
{
"content": "테스트 1",
"completed": false,
"id": 1
},
{
"content": "테스트 2",
"completed": true,
"id": 2
},
{
"content": "테스트 3",
"completed": false,
"id": 3
},
]
}
http://localhost:3000/todos
해당 서버로 들어가면 위의 db.json과 같은 데이터를 조회할 수 있습니다!
데이터 가져오기
>> 초기 HTML 문서를 완전히 불러오고 분석했을 때 발생
window.addEventListener("DOMContentLoaded", (event) => {
console.log("DOM fully loaded and parsed");
});
초기 HTML 문서를 완전히 불러온 뒤 위의 할일 목록들의 데이터들을 가져올 getTodos함수를 실행하도록 다음과 같이 작성하였습니다.
const init = () => {
window.addEventListener("DOMContentLoad", ()=>{
getTodos()
})
}
init()
Fetch API
var url = 'https://example.com/profile';
var data = {username: 'example'};
fetch(url, {
method: 'POST', // or 'PUT'
body: JSON.stringify(data), // data can be `string` or {object}!
headers:{
'Content-Type': 'application/json'
}
}).then(res => res.json())
.then(response => console.log('Success:', JSON.stringify(response)))
.catch(error => console.error('Error:', error));
할일 목록들의 데이터들을 가져올 getTodos함수는 fetch api를 이용하여 작성하였습니다.
const API_URL = 'http://localhost:3000/todos';
const getTodos = () => {
fetch(API_URL)
.then((response) => response.json())
.then((todos) => renderAllTodos(todos))
.catch((error) => console.error(error))
}
이때, todos의 목록을 하나하나 랜더링해줄 함수인 renderAllTodos에 대해 알아보도록하겠습니다.
const get = (target) => {
return document.querySelector(target)
}
const $todos = get('.todos')
const renderAllTodos = (todos) => {
$todos.innerHTML = '' //초기화
todos.forEach((item) => {
const todoElement = createTodoElement(item)
$todos.appendChild(todoElement)
})
}
forEach문을 통해 각 데이터들을 class가 item인 div를 생성해주는 createTodoElement함수에 넣어주고,
todos 클래스 div에 각각 연결해주도록 합니다.
다음과 같이 데이터들이 모두 화면에 나타나는 것을 확인할 수 있다!
데이터(할일) 입력하기
eventListener를 이용하여 입력 데이터를 추가해보도록 구현해보자!
const init = () => {
window.addEventListener("DOMContentLoad", ()=>{
getTodos()
})
$form.addEventListener("submit", addTodo)
}
init()
const addTodo = (e) => {
e.preventDefault()
console.log($todoInput.value)
const todo = {
content: $todoInput.value,
completed: false,
}
fetch(API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(todo),
})
.then(getTodos)
.then(() => {
$todoInput.value = ''
$todoInput.focus()
})
.error((error) => console.error(error))
}
체크박스 변경
const init = () => {
window.addEventListener("DOMContentLoad", ()=>{
getTodos()
})
$form.addEventListener("submit", addTodo)
$todos.addEventListener('click', toggleTodo)
}
init()
해당 데이터들의 id값을 불러오기
const toggleTodo = (e) => {
if (e.target.className !== 'todo_checkbox') return
const $item = e.target.closest('.item')
const id = $item.dataset.id
console.log(id)
}
checkbox를 누를때마다 해당 id를 조회할 수 있다. 이를 바탕으로 db.json 데이터에 각 해당하는 completed부분의 false/true를 변경해주어 checkbox의 상태를 변경해줄 수 있다.
const completed = e.target.checked
fetch(`${API_URL}/${id}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ completed }),
})
.then(getTodos)
.catch((error) => console.error(error))
}
💡 이때, 메소드를 PUT이 아닌 PATCH를 적용한 이유
PUT : 자원의 전체 교체, 자원교체 시 모든 필드 필요
(만약 전체가 아닌 일부만 전달할 경우, 전달한 필드외 모두 null or 초기값 처리됨!!)
PATCH : 자원의 부분 교체, 자원교체시 일부 필드 필요
>> 즉, 우리는 completed 부분만 교체해줄 것이기 때문에 PATCH 메소드를 사용해주도록 하자
추가로, createTodoElement 함수에 다음과 같이 삼항연산자 함수를 작성해주어 completed가 true일 경우 checkbox가 체크되도록 아닐 경우 그대로(false) 두도록 함
const isChecked = completed ? 'checked' : ''
<input
type="checkbox"
class='todo_checkbox'
${isChecked}
/>
결과는 아래에서 확인!
데이터(할일) 수정하기
1. 수정버튼 클릭 시, 버튼바뀌기 설정
<div class="content">
<input
type="checkbox"
class='todo_checkbox'
${isChecked}
/>
<label>${content}</label>
<input type="text" value="${content}" />
</div>
<div class="item_buttons content_buttons">
<button class="todo_edit_button">
<i class="far fa-edit"></i>
</button>
<button class="todo_remove_button">
<i class="far fa-trash-alt"></i>
</button>
</div>
<div class="item_buttons edit_buttons">
<button class="todo_edit_confirm_button">
<i class="fas fa-check"></i>
</button>
<button class="todo_edit_cancel_button">
<i class="fas fa-times"></i>
</button>
</div>
이벤트함수 이용
$todos.addEventListener('click', changeEditMode)
위의 html을 참고하여 (클래스명이 item인 div의 태그들) querySelector로 가져와 변수에 저장해둡니다.
const changeEditMode = (e) => {
const $item = e.target.closest('.item')
const $label = $item.querySelector('label')
const $editInput = $item.querySelector('input[type="text"]')
const $contentButtons = $item.querySelector('.content_buttons')
const $editButtons = $item.querySelector('.edit_buttons')
}
그리고 이어서 if문으로 클릭한 클래스명이 해당 클래스와 같을 경우로 나눠 style효과를 적용해줍니다.
- 수정버튼
- 수정취소 버튼
display
- none : 안보임
- block : 보임
if (e.target.className === 'todo_edit_button') {
$label.style.display = 'none'
$editInput.style.display = 'block'
$contentButtons.style.display = 'none'
$editButtons.style.display = 'block'
}
if (e.target.className === 'todo_edit_cancel_button') {
$label.style.display = 'block'
$editInput.style.display = 'none'
$contentButtons.style.display = 'block'
$editButtons.style.display = 'none'
$editInput.value = $label.innerText
}
2. 수정내용 저장
앞서 체크박스와 마찬가지로 id를 가져온 후, fetch를 이용하여 editTodo 함수를 만들어줍니다.
+ 추가로 변경된 input값도 동일하게 가져와주면 됩니다
const editTodo = (e) => {
if (e.target.className !== 'todo_edit_confirm_button') return
const $item = e.target.closest('.item')
const id = $item.dataset.id
const $editInput = $item.querySelector('input[type="text"]')
const content = $editInput.value
fetch(`${API_URL}/${id}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content }),
})
.then(getTodos)
.catch((error) => console.error(error))
}
📌 수정버튼 클릭 시, 해당 input에 focus 구현 기능을 추가해보자!
$editInput.focus()
>> 해당 input값에 마지막이 아닌 앞쪽에 포커스가 되어버림,,
잠깐의 꼼수를 써보자면,,복붙을 이용해보자!
이를 코드로 구현해보면 다음과 같이 간단함!
이때, value = $editInput.value로 복붙해주기!
$editInput.focus()
$editInput.value = ''
$editInput.value = value
데이터(할일) 삭제하기
const removeTodo = (e) => {
if (e.target.className !== 'todo_remove_button') return
const $item = e.target.closest('.item')
const id = $item.dataset.id
fetch(`${API_URL}/${id}`, {
method: 'DELETE',
})
.then(getTodos)
.catch((error) => console.error(error))
}
마찬가지로 id를 받아와 fetch 시, DELETE 메소드를 이용하여 데이터들을 삭제시키는 것을 구현해준다.
'Front-end > JavaScript' 카테고리의 다른 글
[JavaScript] 함수 (0) | 2023.03.07 |
---|---|
[JavaScript] Pagination 구현 (0) | 2023.02.24 |
[JavaScript] 객체 복사 (0) | 2023.02.16 |
[JavaScript] 배열 (0) | 2023.02.10 |
[JavaScript] 객체 (0) | 2023.02.10 |