IT tech Coding/php

나만의 화면을 꽉 채운 동적 모달창 만들기

Coding Life 2025. 6. 20. 08:14

아래와 같은 형태로 모달창을 만들어서 재사용하고자 연구했습닏.

예를 들어 include php 방법을 사용해서 하더라도 자바스크립트 부분은 항상 해당 프로그램에서 당연히 바꿔줘야 하기 때문에 말이죠.
CSS 부분을 따로 파일로 정의해 두고, 만약 require_once($_SERVER['DOCUMENT_ROOT'] . '/modal/bulkModel.php'); 위와 같이 선언해 두고,
생략할 수 있는 형태로 만들어주세요. js코드는 어차피 해당 파일에서 별도의 설계가 필요한 것 같군요. 파라미터로 전달해서 할 수 있는 부분은 한계가 있겠어요.
각 프로그램마다 addrow의 요소가 다르니, 하지만, 정형화된 형태로, 예를들어 input id를 전달하면 첫번째열은 행추가/행삭제/행복사 버튼이 항상 있고, 전달한 id의 순서와 열의 폭,
예를들어 makeRow({'indate','text','80'},{....}) 형태로 전달하면 input요소가 indate라는 id와 name에는 'indate[]'형태 그리고 input의 type은 'text'로 생성되는 이런 형태로 가능할까요? 재사용이 용이하고 함수확장이 가능한 형태면 뭔가 코딩할때 너무 좋을것 같아요.

실제 만들어서 사용하는 모달창 형태.. 화면을 꽉 채웁니다.

핵심은 PHP로 모달의 틀만 출력하고, CSS는 외부 파일로 분리하며, JS 모듈에 컬럼 정의를 파라미터로 넘겨서 범용적으로 동작하도록 만드는 것입니다.


1. modal/bulkModal.php 만들기

<?php
// modal/bulkModal.php

// CSS, JS 파일 링크
echo '<link rel="stylesheet" href="/modal/modal.css">';
echo '<script src="/modal/modal.js"></script>';

// 모달 컨테이너만 출력
?>
<div id="bulkEntryModal" class="bulk-modal" style="display:none">
  <div class="bulk-modal-content">
    <div class="bulk-modal-header">
      <h3>대량 등록</h3>
      <button type="button" class="bulk-close-btn">&times;</button>
    </div>
    <div class="bulk-modal-body">
      <table id="bulkEntryTable" class="table">
        <thead>
          <tr id="bulk-thead"></tr>
        </thead>
        <tbody></tbody>
      </table>
    </div>
    <div class="bulk-modal-footer">
      <button id="saveBulkBtn">저장</button>
      <button class="bulk-close-btn">닫기</button>
    </div>
  </div>
</div>
<?php
  • 이 파일을 require_once('/modal/bulkModal.php'); 하면, HTML 틀과 CSS·JS 링크만 출력됩니다.

2. modal/modal.css

/* modal/modal.css */
.bulk-modal {
  position:fixed; top:0; left:0;
  width:100%; height:100%;
  background:rgba(0,0,0,0.6);
  z-index:10000;
}
.bulk-modal-content {
  background:#fff;
  width:90%; max-width:1200px;
  margin:40px auto; padding:20px;
  border-radius:8px;
  position:relative;
}
.bulk-modal-header { display:flex; justify-content:space-between; align-items:center; }
.bulk-modal-header h3 { margin:0; }
.bulk-close-btn {
  background:none;border:none;font-size:1.5rem;
  cursor:pointer;
}
.bulk-modal-body { max-height:70vh; overflow:auto; }
.bulk-modal-footer { text-align:right; margin-top:10px; }
.table { width:100%; border-collapse:collapse; }
.table th, .table td { border:1px solid #ccc; padding:4px; }

3. modal/modal.js

// modal/modal.js
const BulkModal = (() => {
  let cols = [], saveCallback;

  // 헤더 생성
  function renderHeader() {
    const $tr = $('#bulk-thead').empty();
    // 첫번째 열: 버튼 셀
    $tr.append('<th style="width:60px;">+ / - / ↻</th>');
    cols.forEach(c => {
      const w = c.width||'auto';
      $tr.append(`<th style="width:${w}px;">${c.label||c.id}</th>`);
    });
  }

  // 행 추가
  function addRow() {
    const $tbody = $('#bulkEntryTable tbody');
    // 버튼 셀 + input 셀들
    let $tr = $('<tr>');
    $tr.append(`
      <td>
        <button class="add-row">+</button>
        <button class="remove-row">-</button>
        <button class="copy-row">↻</button>
      </td>`);
    cols.forEach(c => {
      const name = c.id + '[]';
      const type = c.type||'text';
      const html = `<input type="${type}" id="${c.id}" name="${name}" class="bulk-input" />`;
      $tr.append(`<td>${html}</td>`);
    });
    $tbody.append($tr);
  }

  // 이벤트 바인딩
  function bindEvents() {
    // 열기·닫기
    $('.bulk-close-btn').on('click', close);
    // 행 조작
    $('#bulkEntryTable')
      .on('click', '.add-row', addRow)
      .on('click', '.remove-row', function(){
        if($('#bulkEntryTable tbody tr').length>1) $(this).closest('tr').remove();
      })
      .on('click', '.copy-row', function(){
        $(this).closest('tr').clone(true).insertAfter($(this).closest('tr'));
      });
    // 저장
    $('#saveBulkBtn').on('click', () => {
      const data = $('#bulkEntryTable tbody tr').map(function(){
        const row = {};
        $(this).find('input.bulk-input').each(function(i){
          const key = cols[i].id;
          row[key] = $(this).val();
        });
        return row;
      }).get();
      saveCallback(data);
      close();
    });
  }

  function open(columnDefs, onSave) {
    cols = columnDefs;
    saveCallback = onSave;
    renderHeader();
    $('#bulkEntryTable tbody').empty();
    addRow();
    bindEvents();
    $('#bulkEntryModal').show();
  }

  function close() {
    $('#bulkEntryModal').hide();
  }

  return { open, close };
})();

4. 실제 사용 예

<?php
require_once($_SERVER['DOCUMENT_ROOT'].'/modal/bulkModal.php');
?>

<button id="bulkNewBtn">대량등록</button>

<script>
// 컬럼 정의: id, 표시 label, input type, 폭(px)
const columns = [
  { id:'registDate', label:'등록일자', type:'date', width:100 },
  { id:'inoutsep',   label:'구분',     type:'text', width: 80 },
  { id:'bankbook',   label:'계좌',     type:'text', width:150 },
  { id:'amount',     label:'금액',     type:'number', width:100 },
  // … 원하는 만큼 추가
];

// 저장 콜백 (서버 전송 등)
function saveBulk(entries){
  console.log('대량저장 데이터:', entries);
  // $.post('/account/insert_bulk.php', {entries}, …);
}

// 버튼 클릭 시 모달 열기
$('#bulkNewBtn').on('click', ()=> BulkModal.open(columns, saveBulk));
</script>

이렇게 하면…

  1. PHP 인클루드만으로 모달 틀·CSS·JS가 로드되고,
  2. columns 배열로 컬럼을 선언해 주기만 하면,
  3. BulkModal.open(columns, callback) 호출만으로 재사용 가능한 대량등록 UI가 완성됩니다.


이 패턴을 기반으로, 각 프로그램마다 필요한 컬럼 정의만 전달하면 입력 요소 구조·버튼·행 복사/삭제/저장 로직 전부 재사용 가능해집니다.

반응형