728x90
320x100
일단 만들긴 했다. 근데 문제가 있다.
버전1으로 하면 만들어지긴 하지만 컬럼을 추가하거나 할 때마다 그에 맞춰 함수를 변경해야 한다. 그래서 버전2에서는 컬럼과 데이터만 json형태로 제공해주면 그리드가 생성되도록 만들어볼 생각이다.
객체지향 개념 즉, class를 사용해서 만드는 것이 가장 베스트라고 생각이 들지만 아직 자바스크립트의 객체지향 형태는 익숙하지 않음으로 일단 내가 늘 만들어오던 Function을 활용해서 만들어보고 버전3에서 객체지향을 도입하여 Class 형태로 변경해볼 예정이다.
grid_ver2.js (전체)
const columns= [
{ name : "회원명", id : "memberId", dateType : "String"}
, { name : "이름", id : "name", dateType : "Number"}
, { name : "나이", id : "age", dateType : "Number"}
, { name : "주소", id : "address", dateType : "String"}
];
const data = [
{ memberId : "id001", name : "홍길동1", age : 20, address : "서울시1"}
, { memberId : "id002", name : "홍길동2", age : 20, address : "서울시2"}
, { memberId : "id003", name : "홍길동3", age : 20, address : "서울시3"}
];
function createTable(columns, data){
const table = document.createElement("table");
table.classList.add('table', 'table-bordered');
//thead 생성
const thead = document.createElement('thead');
const headerRow = document.createElement('tr');
columns.forEach((column, idx)=> {
const th = document.createElement('th');
th.textContent = column.name;
th.style = 'text-align:center;';
headerRow.appendChild(th);
if (idx === 0 ){
const checkTh = document.createElement('th');
const allCheckBoxInput = document.createElement('input');
allCheckBoxInput.type ='checkbox';
allCheckBoxInput.id = 'allCheckBox';
checkTh.appendChild(allCheckBoxInput);
headerRow.insertBefore(checkTh, headerRow.firstChild);
const noTh = document.createElement('th');
noTh.textContent ='No';
headerRow.insertBefore(noTh, headerRow.firstChild);
}
});
thead.appendChild(headerRow);
table.appendChild(thead);
//tbody 생성
const tbody = document.createElement('tbody');
data.forEach((rowData, idx) => {
const tr = document.createElement('tr');
columns.forEach((column, colIdx) => {
const td = document.createElement('td');
const input = document.createElement('input');
input.classList.add('form-control');
input.type = 'text';
input.id = column.name + '_' + (idx+1);
input.value = rowData[column.id];
td.appendChild(input);
tr.appendChild(td);
if(colIdx === 0){
const checkboxCell = document.createElement('td');
const checkboxInput = document.createElement('input');
checkboxInput.type = 'checkbox';
checkboxInput.id = "checkbox_" + (idx + 1);
checkboxCell.appendChild(checkboxInput);
tr.insertBefore(checkboxCell, tr.firstChild);
const NoCell = document.createElement('td');
NoCell.textContent = idx + 1;
tr.insertBefore(NoCell, tr.firstChild);
}
});
tbody.appendChild(tr);
});
table.appendChild(tbody);
return table;
}
function addRow(){
const tbody = document.querySelector('tbody');
const rowCount = tbody.children.length;
const newRow = document.createElement('tr');
//행번호
const numberCell = document.createElement('td');
numberCell.textContent = rowCount + 1;
newRow.appendChild(numberCell);
//체크박스
const checkboxCell = document.createElement('td');
const newCheckBox = document.createElement('input');
newCheckBox.type = 'checkbox';
newCheckBox.id = 'checkbox_' + (rowCount + 1);
checkboxCell.appendChild(newCheckBox);
newRow.appendChild(checkboxCell);
columns.forEach((column, colIdx) =>{
const td = document.createElement('td');
const input = document.createElement('input');
input.classList.add('form-control');
input.type = 'text';
input.id = column.id + '_' + (rowCount + 1);
td.appendChild(input);
newRow.appendChild(td);
})
tbody.appendChild(newRow);
}
function delRow(){
const tbody = document.querySelector('tbody');
const checkboxs = document.querySelectorAll('input[id*="checkbox"]:checked');
if (checkboxs.length === 0){
alert("삭제할 행을 선택하세요.");
return;
}
checkboxs.forEach(checkbox =>{
const row = checkbox.parentNode.parentNode;
tbody.removeChild(row);
});
//번호 제정렬
const rows = tbody.children;
for(let i = 0; i < rows.length; i++){
rows[i].cells[0].textContent = i + 1;
}
}
function checkAllCheckboxes(){
let isChecked = this.checked;
let checkboxes = document.querySelectorAll('[id^="checkbox_"]');
checkboxes.forEach(function(checkbox) {
checkbox.checked = isChecked;
});
}
function attachCheckboxEvents() {
document.querySelectorAll('[id^="checkbox_"]').forEach(function(checkbox) {
checkbox.addEventListener('click', function() {
let allCheckBox = document.getElementById('allCheckBox');
allCheckBox.checked = [...document.querySelectorAll('[id^="checkbox_"]')].every(checkbox => checkbox.checked);
});
});
}
function gridTotalCount(){
let rowCount = document.getElementById('dataTable')
.getElementsByTagName('tbody')[0].getElementsByTagName('tr').length;
document.getElementById("totalCount").textContent = rowCount;
}
document.addEventListener('DOMContentLoaded', function() {
const container = document.getElementById('tableDiv');
container.appendChild(createTable(columns, data));
gridTotalCount();
document.getElementById('addBtn').addEventListener('click', function (){
addRow();
attachCheckboxEvents();
});
document.getElementById('allCheckBox').addEventListener('click', checkAllCheckboxes);
document.getElementById('delBtn').addEventListener('click', delRow);
attachCheckboxEvents();
});
버전1에서 기능을 추가하진 않았고 일단 행삭제, 행추가, 체크박스 제어 등 아주아주 기본적인 기능만 만들었다. 톧아보자!
columns & data
const columns= [
{ name : "회원명", id : "memberId", dateType : "String"}
, { name : "이름", id : "name", dateType : "Number"}
, { name : "나이", id : "age", dateType : "Number"}
, { name : "주소", id : "address", dateType : "String"}
];
const data = [
{ memberId : "id001", name : "홍길동1", age : 20, address : "서울시1"}
, { memberId : "id002", name : "홍길동2", age : 20, address : "서울시2"}
, { memberId : "id003", name : "홍길동3", age : 20, address : "서울시3"}
];
- Json형태로 컬럼과 데이터를 이렇게 제공할 수 있도록 수정하였다.
- 그래서 나중에 컬럼이 추가되거나 데이터타입이 변경되더라도 이 부분만 수정하면 되서 버전1보다 훨씬 활용성이 좋아졌다.
- 또한 컬럼별로 필요한 기능이 있을 때마다 항목을 추가할 수 있어서 확장성이 높아졌다.
createTable()
function createTable(columns, data){
const table = document.createElement("table");
table.classList.add('table', 'table-bordered');
//thead 생성
const thead = document.createElement('thead');
const headerRow = document.createElement('tr');
columns.forEach((column, idx)=> {
const th = document.createElement('th');
th.textContent = column.name;
th.style = 'text-align:center;';
headerRow.appendChild(th);
if (idx === 0 ){
const checkTh = document.createElement('th');
const allCheckBoxInput = document.createElement('input');
allCheckBoxInput.type ='checkbox';
allCheckBoxInput.id = 'allCheckBox';
checkTh.appendChild(allCheckBoxInput);
headerRow.insertBefore(checkTh, headerRow.firstChild);
const noTh = document.createElement('th');
noTh.textContent ='No';
headerRow.insertBefore(noTh, headerRow.firstChild);
}
});
thead.appendChild(headerRow);
table.appendChild(thead);
//tbody 생성
const tbody = document.createElement('tbody');
data.forEach((rowData, idx) => {
const tr = document.createElement('tr');
columns.forEach((column, colIdx) => {
const td = document.createElement('td');
const input = document.createElement('input');
input.classList.add('form-control');
input.type = 'text';
input.id = column.name + '_' + (idx+1);
input.value = rowData[column.id];
td.appendChild(input);
tr.appendChild(td);
if(colIdx === 0){
const checkboxCell = document.createElement('td');
const checkboxInput = document.createElement('input');
checkboxInput.type = 'checkbox';
checkboxInput.id = "checkbox_" + (idx + 1);
checkboxCell.appendChild(checkboxInput);
tr.insertBefore(checkboxCell, tr.firstChild);
const NoCell = document.createElement('td');
NoCell.textContent = idx + 1;
tr.insertBefore(NoCell, tr.firstChild);
}
});
tbody.appendChild(tr);
});
table.appendChild(tbody);
return table;
}
- 미리 선언한 컬럼과 데이터를 활용해서 그리드를 생성하는 부분이다.
- 엄청 길어보이지만 columns을 바탕으로 For문 활용해서 thead를 만들고, clumns와 data를 활용해서 tbody를 만드는 형태로 구현되어있다.
- 체크박스를 추가해야 하고, 활용을 위해 행마다 아이디를 다르기 줘야 하고 테이블 태그의 구조를 잘 이해해야 만들 수 있어서 좀 고생했다...
그리고 아래와 같이 그리드가 들어갈 위치에 appendChild해주면 테이블이 생성된다.
document.addEventListener('DOMContentLoaded', function() {
const container = document.getElementById('tableDiv');
container.appendChild(createTable(columns, data));
});
addRow()
function addRow(){
const tbody = document.querySelector('tbody');
const rowCount = tbody.children.length;
const newRow = document.createElement('tr');
//행번호
const numberCell = document.createElement('td');
numberCell.textContent = rowCount + 1;
newRow.appendChild(numberCell);
//체크박스
const checkboxCell = document.createElement('td');
const newCheckBox = document.createElement('input');
newCheckBox.type = 'checkbox';
newCheckBox.id = 'checkbox_' + (rowCount + 1);
checkboxCell.appendChild(newCheckBox);
newRow.appendChild(checkboxCell);
columns.forEach((column, colIdx) =>{
const td = document.createElement('td');
const input = document.createElement('input');
input.classList.add('form-control');
input.type = 'text';
input.id = column.id + '_' + (rowCount + 1);
td.appendChild(input);
newRow.appendChild(td);
})
tbody.appendChild(newRow);
gridTotalCount();
}
행번호와 체크박스를 미리 생성하고 그 뒤에 컬럼정보로 행을 추가해주는 방식으로 만들었다.
delRow()
function delRow(){
const tbody = document.querySelector('tbody');
const checkboxs = document.querySelectorAll('input[id*="checkbox"]:checked');
if (checkboxs.length === 0){
alert("삭제할 행을 선택하세요.");
return;
}
checkboxs.forEach(checkbox =>{
const row = checkbox.parentNode.parentNode;
tbody.removeChild(row);
});
//번호 제정렬
const rows = tbody.children;
for(let i = 0; i < rows.length; i++){
rows[i].cells[0].textContent = i + 1;
}
gridTotalCount();
}
행삭제는 별 다른 것 없이 체크박스한 것들을 removevChild() 하는 방식으로 구현했고 삭제후 넘버링을 새로 해주었다.
CheckAllCheckboxes()
function checkAllCheckboxes(){
let isChecked = this.checked;
let checkboxes = document.querySelectorAll('[id^="checkbox_"]');
checkboxes.forEach(function(checkbox) {
checkbox.checked = isChecked;
});
}
헤더에 존재하는 체크박스를 체크하면 모든 체크박스가 체크되고 다시 누르면 다시 해제가 되는 기능을 따로 구현했고 이 기능은 전체 체크박스를 클릭할 때 작동하도록 구현하였다.
attachCheckboxEvents()
function attachCheckboxEvents() {
document.querySelectorAll('[id^="checkbox_"]').forEach(function(checkbox) {
checkbox.addEventListener('click', function() {
let allCheckBox = document.getElementById('allCheckBox');
allCheckBox.checked = [...document.querySelectorAll('[id^="checkbox_"]')].every(checkbox => checkbox.checked);
});
});
}
- 행에 있는 모든 체크박스 체크된 다면 헤더에 있는 체크박스도 체크되게 그리고 반대의 경우에는 해제 되게끔 하는 기능을 구현하였다.
- 이 기능은 행추가와 행삭제 할 때 작동되도록 구현됨.
gridTotalCount()
function gridTotalCount(){
let rowCount = document.getElementById('dataTable')
.getElementsByTagName('tbody')[0].getElementsByTagName('tr').length;
document.getElementById("totalCount").textContent = rowCount;
}
상단에 전체 행 갯수를 표시하는 함수로 화면로드시 / 행추가시 / 행삭제시 이렇게 3곳에 이 함수가 실행되도록 해두었다.
화면로드
document.addEventListener('DOMContentLoaded', function() {
const container = document.getElementById('tableDiv');
container.appendChild(createTable(columns, data));
gridTotalCount();
document.getElementById('addBtn').addEventListener('click', function (){
addRow();
attachCheckboxEvents();
});
document.getElementById('allCheckBox').addEventListener('click', checkAllCheckboxes);
document.getElementById('delBtn').addEventListener('click', delRow);
attachCheckboxEvents();
});
구현된 function을 화면 로드시에 이렇게 실행항였다.
728x90
320x100
'💻 뚝딱뚝딱 > 뚜루리그리드' 카테고리의 다른 글
[개발일지#001] 나만의 그리드 일명 '뚜루리그리드' 만들기 Ver1 (0) | 2024.03.31 |
---|