0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ローカルストレージでCRUD. ID/ ストレージ・モーダルウィンドウ

Last updated at Posted at 2025-06-12

重要ポイント

 ローカルストレージ使う時IDとワンセット

 IDはhtmlでは隠しとくのが基本
  (編集画面のみIDつける)
  <input type="hidden" id="editId">

 保存の仕組み : テーブルにdata 表示してから保存

 テーブル表示と保存は処理を同時にはしない
 
 保存とテーブル表示はいつも処理別々

ローカルストレージ 作成手順

 1.ローカルストレージ使うための初期設定
 2.data読み込み関数 作成
 3.data保存関数 作成
 4.data取得関数 作成
 5.新規追加 変数 仕込む
 6.data編集 変数仕込む
 7.削除 変数 仕込む

 8.テーブル読み込み 変数 仕込む
   
 9.編集モーダル開く 変数 仕込む

 10.入力formでdata送信ボタン押したらボタンの色を変える
   変数仕込む

           
    code化すると
        
  
  1.ローカルストレージ使うための初期設定 場所 : 最初と最後
     名前"studentData"でローカルストレージ使うよ
  const LOCAL_STORAGE_KEY = 'studentData';
  
   ローカルストレージにはたくさんdataを入れる
  たくさんdataを入れるには配列がいるから配列を用意し
  配列を初期化
    let studentData = [];

    
    
  2.data読み込み関数 作成
  作った配列をローカルストレージにセット
  const storedData = localStorage.getItem(LOCAL_STORAGE_KEY);

  dataはそのままだとJSで扱えないからJSで扱える形にする
  studentData = JSON.parse(storedData);

  ローカルストレージの長さが増えてたらデータが新しく追加された
  ってことだからローカルストレージの長さを数える
   if (studentData.length > 0) {

  data追加時最新IDでdata追加できるよう処理
  nextId = Math.max(...studentData.map(item => item.id)) + 1;

  テーブルの中身を毎回からにし入力欄でdataを新規作成にするには
  テーブル初期化しないといけないからテーブル初期化
  renderTable(); 
    

 3.data保存関数 作成
 JSで扱えるようにしたdataを画面に表示できるよう 設定
    function saveDataToLocalStorage() {
    localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(studentData));
  }
    

  5.新規追加 変数 仕込む
  idの初期値はローカルストレージに保存されてて
  最初のidはローカルストレージから引っ張って来ないと
  使えないから push使う
    studentData.push({ ...data, id: nextId++ }); // IDを更新

    data保存とテーブル初期化関数 呼び出し
      saveDataToLocalStorage();
      renderTable();

    data を作り終えたら入力formはからにしないと
    data を新規作成できないから入力formをからに
      clearFormInputs();
    
  6.data編集 変数仕込む
  index でIDを指定し指定したID 探す
  findIndex : dataがローカルストレージの何番目に入ってるか
   探す(何番目に入ってるか要素番号調べないとdataを正しく
   編集できないから)
  const index = studentData.findIndex(item => item.id === id);

  探したIDがあったらdataを更新するから index !== -1
      if (index !== -1) {

  探したIDでローカルストレージにdataを代入し更新
        studentData[index] = { ...studentData[index], ...updatedData };

  data保存テーブル初期化
    saveDataToLocalStorage();
        renderTable();
    
  7.削除 変数 仕込む
  削除するID指定 ; itemしID削除されてるか確認
  studentData = studentData.filter(item => item.id !== id);

  data 保存テーブル初期化
  saveDataToLocalStorage();
      renderTable();
    
          
  8.テーブル空欄に 変数 仕込む
  テーブルにdata新規追加を新しくやる時
  テーブルの全項目を空にしないといけなくて
  テーブルの全項目を空にするにはforeach使わないとできないから
  やってる
    function renderTable() {
    tableBody.innerHTML = ''; // テーブルの中身をクリア
    studentData.forEach(data => addTableRow(data)); // 全てのデータを再描画
  }
    
   9.編集モーダル開く 変数 仕込む
   すでにあるidを探し探したidをもとにdata編集
    const dataToEdit = studentData.find(item => item.id === id);
    

  10.入力formでdata送信ボタン押したらボタンの色を変える
     変数仕込む
     ボタンの色を変える時ローカルストレージのdataを
     読み込んでからボタンの色を変えないとdata 読み込みなしで
     ボタンの色を変えたら エラーになるらしい
      oadDataFromLocalStorage();
      addButton.addEventListener('click', () => {
      addButton.classList.add('clicked-button'); 

ID使い、 ローカルストレージで保存 仕組み

  1.データ初期設定
    IDの初期値 設定

   2.ID最大値を探し今のid読み込み
    IDの最大値を探しIDを常に+1しておく
    dataが新規作成されたらIDは常に最大値になるから
    IDは数字だから数字を扱う時maoでいつも処理

   3.入力data取得 
    idは呼び出すのみ

   4.新規追加
   id増やす
   
   5.data編集 変数仕込む
   同じID探す
   ID探してからじゃないと編集dataをストレージから
   常に引っ張って来れないから使うのがfind

   7.削除
   IDは消したら無くなるからなくなったID探す
   IDがなく存在しなくなったことを確認してから
   出ないとdataを安全に消せないから調べてる"filter"

   8.テーブル表示 : idセット
   
   編集ボタン押した / 削除ボタン押した / 編集modal開いた
   / 編集モーダル開き保存
    id渡す "id渡してないと、data反映できない”から


          code化すると
             ↓
    
    1.データ初期設定
    let nextId = 1;

         ↓
    2.ID最大値を探し、今のid読み込み
    nextId = Math.max(...studentData.map(item => item.id)) + 1;
    
             ↓
   3.入力data取得 :id 読み込み
    id: nextId,
    
    ↓
   4.新規追加: id増やす
   studentData.push({ ...data, id: nextId++ });
    ↓

   5.data編集 : 同じID探す
   findIndex : dataがローカルストレージの何番目に入ってるか
   探す(何番目に入ってるか、要素番号調べないとdataを正しく
   編集できないから)
   const index = studentData.findIndex(item => item.id === id);
    ↓

  7.削除 : 消したID探す
  studentData = studentData.filter(item => item.id !== id);
    ↓
  8.テーブル表示 : idセット
  row.setAttribute('data-id', data.id);

    ↓
  編集ボタン押したら、idセット
  editButton.addEventListener('click', () => {
      openEditModal(data.id); // 編集モーダルを開く
    });
    ↓

  削除ボタン押したら、idセット
  deleteButton.addEventListener('click', () => {
      deleteData(data.id); // データ削除関数を呼び出す
    });

    ↓
  編集ボタン押してモーダルウィンドウ開く時、idセットし、
  id探す
   function openEditModal(id) {
   const dataToEdit = studentData.find(item => item.id === id);
    ↓
  
 編集画面で、id表示
 editIdInput.value = dataToEdit.id;
    ↓

 保存先を指定し、保存(保存先 : 編集画面のid)
 const id = parseInt(editIdInput.value);
    ↓

 バリデーションさせた後、dataを保存するから、
 バリデーション後は、もう一度idを呼び出して保存
 updateData(id, updatedData);

ボタンの色を変える 仕組み

 ボタンの色を変えるクラスをcssに設定
 ボタンの初期値セット
 dataを読み込んで
 追加ボタン押したらボタンの色変える
 入力formのdataを取得し表示
 バリデーション無効に


        code化すると
            

  ボタンの色を変えるクラスをcssに設定
   #addButon.clicked-button {
        background-color: #28a745; /* クリック後は別の色(例: 緑) */
    }
           
 ボタンの初期値セット
document.addEventListener('DOMContentLoaded', () => {
const addButton = document.getElementById('addButon');

                
   dataを読み込んで
 loadDataFromLocalStorage();

                
  追加ボタン押したらボタンの色変える
  addButton.addEventListener('click', () => {
    addButton.classList.add('clicked-button'); 

               
    入力formのdataを取得し表示
     ボタンの色を変えた後も入力formのdataを表示しとか
      なきゃいけないから
    const formData = getFormData();
    
             
   バリデーション無効に
    バリデーションを効かせないためにバリデーション時
    表示するdivを表示させないようにする
    clearErrors();

                  
    バリデーションさせてなかったら処理続ける
    if (!validateForm(formData)) return;

    data新規追加テーブルにdata表示の前の処理)
    createData(formData); 
  });

編集・削除ボタン 追加 仕組み

  やり方: テーブル表示のすぐ後

  # 仕込む場所 : テーブル表示する変数
  function addTableRow(data) {
  html テーブル
  html 削除ボタン
  html 編集ボタン
  tableBody.appendChild(row);
  
      
 これのすぐ後に編集と削除ボタン追加
 ボタンが押されたらイベントリスナー設定


       code化すると
          
  編集と削除ボタン追加(querySelector)
  const editButton = row.querySelector('.edit-button');
    const deleteButton = row.querySelector('.delete-button');

         
  ボタンが押されたらイベントリスナー設定
  editButton.addEventListener('click', () => {
      openEditModal(data.id); // 編集モーダルを開く
    });
  deleteButton.addEventListener('click', () => {
      deleteData(data.id); // データ削除関数を呼び出す
    });
  } 

モーダルウィンドウ 作成仕組み

 ばつボタン/ モーダルウィンドウ,
 キャンセルボタン / 保存ボタンのスタイル設定
 
 編集画面 idはテーブル表示では隠しておく
  
 モーダルウィンドウ全体のdiv id 読み込み
 
 ばつボタン 表示させるため、❌ボタンのクラス表示させる
 
 [編集画面]保存ボタン ID読み込み
 
 [編集画面]キャンセルボタン ID読み込み
 
 [編集画面] id / 電話番号/ 年齢 / 名前 / Eメール ID読み込み
 
 編集関数作成しローカルストレージにdata保存
 モーダルを閉じる関数だけ 仕込む
   編集画面開いた時編集せず
    モーダル閉じたい場合もあるから

 編集ボタンが押されたらモーダルを開く関数 仕込む

 編集モーダル開く関数 作成
 
 編集モーダル閉じる関数 作成
   画面を消すからdisplay none

 ボタンの色を変える関数の後にばつボタンと
 キャンセルボタンでモーダルを閉じる処理 作成

 モーダルの保存ボタンでdata保存する関数 作成

 data編集関数呼び出しdata更新

      code化
        
 モーダルウィンドウのスタイル設定
            
変種画面 idはテーブル表示では隠しておく
  <input type="hidden" id="editId">

        
  モーダルウィンドウ全体のdiv id 読み込み
  document.addEventListener('DOMContentLoaded', () => {
   const editModal = document.getElementById('editModal');
        
  ばつボタン 表示させるため、❌ボタンのクラス表示させる
  const closeButton = document.querySelector('.close-button');
        
  [編集画面]保存ボタン ID読み込み
  const saveEditButton = document.getElementById('saveEditButton');
        
        
  [編集画面]キャンセルボタン ID読み込み
  const cancelEditButton = document.getElementById('cancelEditButton');
  
        
  [編集画面] id / 電話番号/ 年齢 / 名前 / Eメール ID読み込み
  const editIdInput = document.getElementById('editId');
  const editNameInput = document.getElementById('editName');
  const editAgeInput = document.getElementById('editAge');
  const editEmailInput = document.getElementById('editEmail');
  const editPhoneInput = document.getElementById('editPhone');

        
 編集関数作成
 async function updateData(id, updatedData) {
    try {
      // ダミーAPIはPUT/PATCHしても実際のデータは更新しないため、擬似的な成功とします
      const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`, { // ダミーAPI
        method: 'PUT', // または 'PATCH'
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(updatedData)
      });
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      const result = await response.json();
      console.log('APIでデータが更新されました:', result);

      // 成功したらローカルデータとLocalStorageを更新
      const index = studentData.findIndex(item => item.id === id);
      if (index !== -1) {
        studentData[index] = { ...studentData[index], ...updatedData };
        saveDataToLocalStorage();
        renderTable();
      }

 編集関数にモーダル閉じる関数 仕込む
   モーダル開いても何も処理しないで画面閉じたい時もあるから
  }
      closeEditModal(); // 編集成功後にモーダルを閉じる
    } catch (error) {
      console.error('データ更新に失敗しました:', error);
      alert('データ更新に失敗しました。');
    }
    
        
  編集ボタンが押されたらモーダルを開く関数 仕込む
  editButton.addEventListener('click', () => {
      openEditModal(data.id); // 編集モーダルを開く
    });
    
        
  編集モーダル開く関数 作成
  function openEditModal(id) {
    const dataToEdit = studentData.find(item => item.id === id);
    if (dataToEdit) {
      editIdInput.value = dataToEdit.id;
      editNameInput.value = dataToEdit.name;
      editAgeInput.value = dataToEdit.age;
      editEmailInput.value = dataToEdit.email;
      editPhoneInput.value = dataToEdit.phone;
      editModal.style.display = 'flex'; // flexにして中央寄せを有効に
    }
        
  編集モーダル閉じる関数 作成
  function closeEditModal() {
    editModal.style.display = 'none';
  }
        
  ボタンの色を変える関数の後にばつボタンと
 キャンセルボタンでモーダルを閉じる処理 作成
  closeButton.addEventListener('click', closeEditModal);  ばつボタン
  cancelEditButton.addEventListener('click', closeEditModal);    キャンセルボタン

        
 モーダルの保存ボタンが押されたらイベントリスナーで
 dataを画面に表示関数作成
  saveEditButton.addEventListener('click', () => {
    const id = parseInt(editIdInput.value);
    const updatedData = {
      name: editNameInput.value.trim(),
      age: parseInt(editAgeInput.value.trim()),
      email: editEmailInput.value.trim(),
      phone: editPhoneInput.value.trim()
    };
        
    data保存関数[編集のみの]呼び出しdata更新
      updateData(id, updatedData); 

code全文

!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>テーブル表示練習</title>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <style>
    body {
        font-family: Arial, sans-serif;
        margin: 20px;
    }
    .form-group { margin-bottom: 10px; }
    .label { display: inline-block; width: 80px; }
    .error-message { display:none; color:red; margin-left:5px; }

    /* テーブル全体の基本スタイル */
    table {
        width: 100%;
        border-collapse: collapse;
        margin-top: 20px;
    }
    table, th, td { border:1px solid #000; border-collapse:collapse; padding:5px; }

    /* テーブルヘッダーの枠線を太くする */
    th {
        border: 3px solid #000; /* ヘッダーの枠線を太く */
    }

    /* ボタンの初期スタイル */
    #addButon {
        padding: 8px 15px;
        font-size: 16px;
        cursor: pointer;
        background-color: #007bff; /* 初期の色(青) */
        color: white;
        border: none;
        border-radius: 4px;
        transition: background-color 0.3s ease; /* 色の変化を滑らかに */
    }

    /* ボタンがクリックされた後のスタイル */
    #addButon.clicked-button {
        background-color: #28a745; /* クリック後は別の色(例: 緑) */
    }

    /* 削除・編集ボタンのスタイル */
    .action-button {
        padding: 5px 10px;
        margin-left: 5px; /* ボタン間のスペース */
        border: none;
        border-radius: 3px;
        cursor: pointer;
        font-size: 13px;
        color: white;
    }

    .delete-button {
        background-color: #dc3545; /* 赤色 */
    }

    .edit-button {
        background-color: #ffc107; /* 黄色 */
        color: black; /* 黄色には黒文字が見やすい */
    }

    /* --- モーダルウィンドウのスタイル --- */
    .modal {
      display: none; /* 初期状態では非表示 */
      position: fixed; /* 画面に固定 */
      z-index: 1; /* 最前面に表示 */
      left: 0;
      top: 0;
      width: 100%; /* 全幅 */
      height: 100%; /* 全高 */
      overflow: auto; /* スクロール可能にする */
      background-color: rgba(0,0,0,0.4); /* 半透明の黒背景 */
      justify-content: center;
      align-items: center;
    }

    .modal-content {
      background-color: #fefefe;
      margin: auto; /* 中央寄せ */
      padding: 20px;
      border: 1px solid #888;
      width: 80%; /* 幅 */
      max-width: 500px; /* 最大幅 */
      border-radius: 8px;
      box-shadow: 0 4px 8px rgba(0,0,0,0.2);
      position: relative;
    }

    .close-button {
      color: #aaa;
      float: right;
      font-size: 28px;
      font-weight: bold;
    }

    .close-button:hover,
    .close-button:focus {
      color: black;
      text-decoration: none;
      cursor: pointer;
    }

    .modal-buttons {
      margin-top: 20px;
      text-align: right;
    }
    .modal-buttons button {
      padding: 8px 15px;
      margin-left: 10px;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }
    .modal-buttons .save-button {
      background-color: #28a745;
      color: white;
    }
    .modal-buttons .cancel-button {
      background-color: #6c757d;
      color: white;
    }
  </style>
</head>
<body>

<form id="userForm">
  <div class="form-group">
    <label class="label" for="studentName">名前</label>
    <input type="text" id="studentName">
    <div id="nameError" class="error-message">名前を入力してください</div>
  </div>
  <div class="form-group">
    <label class="label" for="studentAge">年齢</label>
    <input type="number" id="studentAge">
  </div>
  <div class="form-group">
    <label class="label" for="studentEmail">メール</label>
    <input type="email" id="studentEmail">
  </div>
  <div class="form-group">
    <label class="label" for="studentnumber">電話</label>
    <input type="text" id="studentnumber">
  </div>
  <button type="button" id="addButon">追加</button>
</form>

<hr>

<table id="studentTable">
  <thead>
    <tr><th>ID</th><th>名前</th><th>年齢</th><th>メール</th><th>電話</th><th>操作</th></tr> </thead>
  <tbody></tbody>
</table>

<div id="editModal" class="modal">
  <div class="modal-content">
    <span class="close-button">&times;</span>
    <h2>データ編集</h2>
    <input type="hidden" id="editId">
    <div class="form-group">
      <label class="label" for="editName">名前</label>
      <input type="text" id="editName">
    </div>
    <div class="form-group">
      <label class="label" for="editAge">年齢</label>
      <input type="number" id="editAge">
    </div>
    <div class="form-group">
      <label class="label" for="editEmail">メール</label>
      <input type="email" id="editEmail">
    </div>
    <div class="form-group">
      <label class="label" for="editPhone">電話</label>
      <input type="text" id="editPhone">
    </div>
    <div class="modal-buttons">
      <button class="save-button" id="saveEditButton">保存</button>
      <button class="cancel-button" id="cancelEditButton">キャンセル</button>
    </div>
  </div>
</div>

<script>
document.addEventListener('DOMContentLoaded', () => {
  const LOCAL_STORAGE_KEY = 'studentData'; // ローカルストレージのキー

  const addButton = document.getElementById('addButon');
  const nameInput = document.getElementById('studentName');
  const ageInput = document.getElementById('studentAge');
  const emailInput = document.getElementById('studentEmail');
  const phoneInput = document.getElementById('studentnumber');
  const nameError = document.getElementById('nameError');
  const tableBody = document.querySelector('#studentTable tbody');

  // モーダル関連要素
  const editModal = document.getElementById('editModal');
  const closeButton = document.querySelector('.close-button');
  const saveEditButton = document.getElementById('saveEditButton');
  const cancelEditButton = document.getElementById('cancelEditButton');
  const editIdInput = document.getElementById('editId');
  const editNameInput = document.getElementById('editName');
  const editAgeInput = document.getElementById('editAge');
  const editEmailInput = document.getElementById('editEmail');
  const editPhoneInput = document.getElementById('editPhone');

  let studentData = []; // アプリケーションのデータ配列
  let nextId = 1; // 次に割り当てるID

  // --- ローカルストレージとデータ管理 ---

  // ローカルストレージからデータを読み込む
  function loadDataFromLocalStorage() {
    const storedData = localStorage.getItem(LOCAL_STORAGE_KEY);
    if (storedData) {
      studentData = JSON.parse(storedData);
      // 既存データから最大のIDを見つけてnextIdを設定
      if (studentData.length > 0) {
        nextId = Math.max(...studentData.map(item => item.id)) + 1;
      }
      renderTable(); // テーブルを初期表示
    }
  }

  // ローカルストレージにデータを保存する
  function saveDataToLocalStorage() {
    localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(studentData));
  }

  // --- 関数定義 ---

  // 入力データ取得
  function getFormData() {
    return {
      id: nextId, // 現在のnextIdを割り当てる
      name: nameInput.value.trim(),
      age: parseInt(ageInput.value.trim()) || 0, // 数値に変換、無効な場合は0
      email: emailInput.value.trim(),
      phone: phoneInput.value.trim()
    };
  }

  // バリデーション
  function validateForm(data) {
    if (data.name === '') {
      nameError.style.display = 'inline';
      setTimeout(() => { nameError.style.display = 'none'; }, 2000);
      return false;
    }
    if (isNaN(data.age) || data.age <= 0) {
      alert('正しい年齢を入力してください'); // ここは残しておきます
      return false;
    }
    return true;
  }

  // バリデーションエラー初期化
  function clearErrors() {
    nameError.style.display = 'none';
  }

  // --- CRUD操作(Fetch APIを使用) ---

  // データ新規追加 (Create)
  async function createData(data) {
    try {
      const response = await fetch('https://jsonplaceholder.typicode.com/users', { // ダミーAPI
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
      });
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      const result = await response.json();
      console.log('APIから新規データが追加されました:', result);
      
      // 成功したらローカルデータとLocalStorageを更新
      studentData.push({ ...data, id: nextId++ }); // IDを更新
      saveDataToLocalStorage();
      renderTable();
      clearFormInputs();
    } catch (error) {
      console.error('データ追加に失敗しました:', error);
      alert('データ追加に失敗しました。');
    }
  }

  // データ編集 (Update)
  async function updateData(id, updatedData) {
    try {
      // ダミーAPIはPUT/PATCHしても実際のデータは更新しないため、擬似的な成功とします
      const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`, { // ダミーAPI
        method: 'PUT', // または 'PATCH'
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(updatedData)
      });
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      const result = await response.json();
      console.log('APIでデータが更新されました:', result);

      // 成功したらローカルデータとLocalStorageを更新
      const index = studentData.findIndex(item => item.id === id);
      if (index !== -1) {
        studentData[index] = { ...studentData[index], ...updatedData };
        saveDataToLocalStorage();
        renderTable();
      }
      closeEditModal(); // 編集成功後にモーダルを閉じる
    } catch (error) {
      console.error('データ更新に失敗しました:', error);
      alert('データ更新に失敗しました。');
    }
  }

  // データ削除 (Delete)
  async function deleteData(id) {
    const confirmDelete = confirm('本当に削除しますか?');
    if (!confirmDelete) return;

    try {
      const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`, { // ダミーAPI
        method: 'DELETE'
      });
      if (!response.ok) {
        // DELETEリクエストは200 OKまたは204 No Contentを返すことが一般的
        // ここでは200番台以外のエラーを捕捉
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      console.log(`APIからID ${id} のデータが削除されました。`);

      // 成功したらローカルデータとLocalStorageを更新
      studentData = studentData.filter(item => item.id !== id);
      saveDataToLocalStorage();
      renderTable();
    } catch (error) {
      console.error('データ削除に失敗しました:', error);
      alert('データ削除に失敗しました。');
    }
  }

  // --- UI操作 ---

  // テーブルに行追加(編集・削除ボタン付き)
  function addTableRow(data) {
    const row = document.createElement('tr');
    row.setAttribute('data-id', data.id); // 行にデータのIDを設定
    row.innerHTML = `
      <td>${data.id}</td> <td>${data.name}</td>
      <td>${data.age}</td>
      <td>${data.email}</td>
      <td>${data.phone}</td>
      <td>
        <button class="action-button edit-button">編集</button>
        <button class="action-button delete-button">削除</button>
      </td>
    `;
    tableBody.appendChild(row);

    // 追加したばかりのボタンにイベントリスナーを設定
    const editButton = row.querySelector('.edit-button');
    const deleteButton = row.querySelector('.delete-button');

    editButton.addEventListener('click', () => {
      openEditModal(data.id); // 編集モーダルを開く
    });

    deleteButton.addEventListener('click', () => {
      deleteData(data.id); // データ削除関数を呼び出す
    });
  }

  // 入力欄クリア
  function clearFormInputs() {
    nameInput.value = '';
    ageInput.value = '';
    emailInput.value = '';
    phoneInput.value = '';
  }

  // テーブルを再描画する関数
  function renderTable() {
    tableBody.innerHTML = ''; // テーブルの中身をクリア
    studentData.forEach(data => addTableRow(data)); // 全てのデータを再描画
  }

  // 編集モーダルを開く関数
  function openEditModal(id) {
    const dataToEdit = studentData.find(item => item.id === id);
    if (dataToEdit) {
      editIdInput.value = dataToEdit.id;
      editNameInput.value = dataToEdit.name;
      editAgeInput.value = dataToEdit.age;
      editEmailInput.value = dataToEdit.email;
      editPhoneInput.value = dataToEdit.phone;
      editModal.style.display = 'flex'; // flexにして中央寄せを有効に
    }
  }

  // 編集モーダルを閉じる関数
  function closeEditModal() {
    editModal.style.display = 'none';
  }

  // --- イベントリスナー ---

  // ページロード時にローカルストレージからデータを読み込み、テーブルを表示
  loadDataFromLocalStorage();

  // 「追加」ボタンのクリックイベント
  addButton.addEventListener('click', () => {
    // ボタンの色を青に変更 (今回はクリック後に緑に変える例)
    addButton.classList.add('clicked-button'); 

    const formData = getFormData();
    clearErrors();

    if (!validateForm(formData)) return;

    createData(formData); // データ追加関数を呼び出す
  });

  // モーダルを閉じるボタン
  closeButton.addEventListener('click', closeEditModal);
  cancelEditButton.addEventListener('click', closeEditModal);

  // モーダル内の保存ボタン
  saveEditButton.addEventListener('click', () => {
    const id = parseInt(editIdInput.value);
    const updatedData = {
      name: editNameInput.value.trim(),
      age: parseInt(editAgeInput.value.trim()),
      email: editEmailInput.value.trim(),
      phone: editPhoneInput.value.trim()
    };

    if (!validateForm(updatedData)) return; // 編集フォームのバリデーションも既存関数を利用

    updateData(id, updatedData); // データ更新関数を呼び出す
  });
});
</script>

</body>
</html>
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?