irfanhfzh
irfanhfzh

Reputation: 33

Javascript Displaying Data From Local Storage Array Problem

I'm creating a Simple CRUD Application with Javascript and I'm having a problem in Display Data Table from local Storage.

It's like making a TODO List but this is with a Table and enter the data in one row and in a column.

I don't know how to explain the problem clearly, the important thing is that I want the results from my input form and submit to local storage to be displayed correctly in the table.

This is The Code :

const 
  myForm       = document.forms['my-form']  // form name pada tag html form
, table        = document.querySelector('#myTable tbody')
, dataArr       = JSON.parse(localStorage.getItem('dataArr') || '[]');

var selectedRow = null
var number = 0

// Tabel init
dataArr.forEach(row=>{
    let newRow = table.insertRow()

    newRow.insertCell().textContent = row.no = ++number
    newRow.insertCell().textContent = row.inputNL
    newRow.insertCell().textContent = row.inputJK
    newRow.insertCell().textContent = row.inputNH
    newRow.insertCell().textContent = row.inputA 
    newRow.insertCell().innerHTML = `<a onClick="onDelete(this)"><i class="fas fa-times"></i></a>`
})

function onFormSubmit() {
    if (validate()) {
        if (selectedRow == null) {
            // Menambahkan entri ke LocalStorage :
            dataArr.push(Object.fromEntries(new FormData(myForm).entries()))
            localStorage.setItem('dataArr', JSON.stringify( dataArr ))
            
            // Memasukkan Data pada Baris Baru
            let newRow = table.insertRow()
            
            newRow.insertCell().textContent = myForm.no.value = ++number
            newRow.insertCell().textContent = myForm.inputNL.value
            newRow.insertCell().textContent = myForm.inputJK.value
            newRow.insertCell().textContent = myForm.inputNH.value
            newRow.insertCell().textContent = myForm.inputA.value
            newRow.insertCell().innerHTML = `<a onClick="onDelete(this)"><i class="fas fa-times"></i></a>` 
        } 
        resetForm();
    }
}

// Function untuk Mereset Data yang sudah diSumbit di dalam Input
function resetForm() {
    document.getElementById("no").value = "";
    document.getElementById("inputNL").value = "";
    document.getElementById("inputJK").value = "Pria";
    document.getElementById("inputNH").value = "";
    document.getElementById("inputA").value = "";
    selectedRow = null;
}

// Function untuk Delete Data
function onDelete(td) {
    if (confirm('Apa kamu yakin ingin Menghapus Data ini?')) {
        row = td.parentElement.parentElement;
        document.getElementById("myTable").deleteRow(row.rowIndex);
        resetForm();
    }
    hapusDataLocal(td.parentElement.parentElement)
}

function hapusDataLocal(dataItem) {    
    dataArr.forEach(function(task, index) {
        if (dataItem.textContent === task ) {            
            dataArr.splice(index, 1);
        }
    });
    localStorage.setItem(dataArr, JSON.stringify(dataArr))
}

// Function untuk Memvalidasi Data
function validate() {
    isValid = true;
    if (document.getElementById("inputNL").value == "" || document.getElementById("inputJK").value == "" || document.getElementById("inputNH").value == "" || document.getElementById("inputA").value == "") {
        isValid = false;
        alert("Isi Semua Formnya dengan Benar!");
    } 
    return isValid;
}
    <!-- Registration Form -->
    <div class="container w-50 mt-3 shadow p-3 mb-5 bg-white rounded">
      <div class="p-3">
          <h1 class="mb-4">Registration Form</h1>
            <form class="task-form" name="my-form" onsubmit="event.preventDefault();onFormSubmit();" autocomplete="off">
              <input type="hidden" name="no" id="no" value=""> 
              <label for="inputNL" class="form-label">Nama Lengkap</label>
              <input type="text" id="inputNL" name="inputNL" class="form-control mb-2" placeholder="Nama Lengkap">
              <label for="inputJK"class="form-label">Jenis Kelamin</label>
              <select class="form-select mb-2" id="inputJK" name="inputJK">
                <option value="Pria">Pria</option>
                <option value="Wanita">Wanita</option>
              </select>            
              <label for="inputNH" class="form-label">No HP</label>
              <input type="number" id="inputNH" name="inputNH" class="form-control mb-2" placeholder="No HP">
              <label for="inputA" class="form-label">Alamat</label>
              <textarea id="inputA" name="inputA" class="form-control mb-2" style="min-width: 100%" placeholder="Alamat"></textarea>
              <input type="submit" value="Submit" class="btn btn-primary btn-md my-3">
            </form>
      </div>
    </div>
    <!-- Table -->
    <div class="container mt-3 shadow p-3 mb-5 bg-white rounded">
      <div class="p-3">
        <table class="table" id="myTable">
          <thead>
              <th scope="col">#</th>
              <th scope="col">Nama Lengkap</th>
              <th scope="col">Jenis Kelamin</th>
              <th scope="col">No HP</th>
              <th scope="col">Alamat</th>
              <th scope="col">Aksi</th>
          </thead>
          <tbody>

          </tbody>
        </table>
      </div>      
    </div>

Here is The Problem in The Table, The data does not match the column.

enter image description here

And the actual result I want is like this.

enter image description here

Upvotes: 2

Views: 535

Answers (2)

Mister Jojo
Mister Jojo

Reputation: 22265

First of all:

  1. change
 <form class="task-form" name="my-form" onsubmit="event.preventDefault();onFormSubmit();" autocomplete="off">

to

 <form class="task-form" name="my-form" autocomplete="off">

Js code for that is :

const 
  myForm = document.forms['my-form']  // form name pada tag html form

//.... 

myForm.onsubmit = e =>
  {
  e.preventDefault() 
  //...
  1. add my CSS from snippet below (masked)

How do you delete the local storage data?

There were some inconsistencies in the management of no.
I made a few other fixes. Deleting a <table><TR> works...

And please don't use getElementById for form elements!
see how I coded your validate() function
see my previous posts on this point : Jun 30 at 13:06 and Jun 14 '19 at 14:17

I'm like all coders, once I get started on a project I can't just leave it halfway. I hope this will help you better finalize yours.

I got a bit of a headache on the display of the text address transposed in the table, with its overflow problems; hence the idea of the regex to at least remove unnecessary white lines ...
so, see also Single regex to remove empty lines and double spaces from multiline input

const 
  myForm  = document.forms['my-form']  // form name pada tag html form
, myTable = document.querySelector('#myTable')
, myTbody = document.querySelector('#myTable tbody')
, dataArr = JSON.parse(localStorage.getItem('dataArr') || '[]')
, rowsInfo =
    { last_no  : 0
    , noSelect : true
    , index    : 0
    , tRow     : null
    }
, addTableRow = row =>
    {
    rowsInfo.last_no = Math.max( rowsInfo.last_no, row.no )

    let newRow = myTbody.insertRow()
      newRow.insertCell().textContent = row.no 
      newRow.insertCell().textContent = row.inputNL
      newRow.insertCell().textContent = row.inputJK
      newRow.insertCell().textContent = row.inputNH
      newRow.insertCell().innerHTML = `<div>${row.inputA}</div>`
      newRow.insertCell().innerHTML = `<i class="fas fa-times"></i>`
    };
dataArr.forEach(addTableRow) // Tabel init
  ;
myForm.onsubmit = e =>
  {
  e.preventDefault() 
  if (validate())
    {
    if (rowsInfo.noSelect)
      {
      let newRow = Object.fromEntries(new FormData(myForm).entries())
      newRow.no  = ++rowsInfo.last_no

      dataArr.push(newRow)
      addTableRow (newRow) // Memasukkan Data pada Baris Baru
      } 
    else
      {
      let
        index = rowsInfo.index
      , eTR   = rowsInfo.tRow
        ;
      eTR.cells[1].textContent = dataArr[index].inputNL = myForm.inputNL.value 
      eTR.cells[2].textContent = dataArr[index].inputJK = myForm.inputJK.value 
      eTR.cells[3].textContent = dataArr[index].inputNH = myForm.inputNH.value 
      dataArr[index].inputA    = myForm.inputA.value 
      eTR.cells[4].innerHTML   = `<div>${myForm.inputA.value}</div>`

      eTR.classList.remove('selected')
      }
    localStorage.setItem('dataArr', JSON.stringify( dataArr )) // Menambahkan entri ke LocalStorage 
    resetForm()
    }
  }
function resetForm() // Function untuk Mereset Data yang sudah diSumbit di dalam Input
  {
  myForm.reset()
  rowsInfo.noSelect = true
  }
function validate()  // Function untuk Memvalidasi Data
  {
  myForm.inputNL.value = myForm.inputNL.value.trim()
  myForm.inputJK.value = myForm.inputJK.value.trim()
  myForm.inputNH.value = myForm.inputNH.value.trim()
  myForm.inputA.value  = myForm.inputA.value.replace(/^\s*$[\r\n]*|^[^\S\r\n]+|[^\S\r\n]+$|([^\S\r\n]){2,}/gm, '$1') 
  myForm.inputA.value  = myForm.inputA.value.replace(/\n*$/, '')  // remove final line break

  let isValid = 
    ( myForm.inputNL.value !== '' 
   && myForm.inputJK.value !== '' 
   && myForm.inputNH.value !== ''
   && myForm.inputA.value  !== '' 
    ) 
  if (!isValid) alert('Isi Semua Formnya dengan Benar!')
    ;
  return isValid
  }
myTbody.onclick = ({target}) =>
  {
  let
    eTR   = target.closest('tr')
  , rowNo = parseInt( eTR.cells[0].textContent )
  , index = dataArr.findIndex(x=>x.no===rowNo)
  , isDel = target.matches('i.fa-times, td:nth-of-type(6)')
    ;
  if (!eTR.classList.toggle('selected') && !isDel )
    {
    resetForm()
    }
  else 
    {
    myTbody.querySelectorAll('tr').forEach(tr=>tr.classList.toggle('selected', eTR===tr))
 
    rowsInfo.noSelect    = false
    rowsInfo.index       = index
    rowsInfo.tRow        = eTR
    myForm.no.value      = dataArr[index].no
    myForm.inputNL.value = dataArr[index].inputNL
    myForm.inputJK.value = dataArr[index].inputJK
    myForm.inputNH.value = dataArr[index].inputNH
    myForm.inputA.value  = dataArr[index].inputA
    
    if (isDel && confirm('Apa kamu yakin ingin Menghapus Data ini?'))
      {
      dataArr.splice(index, 1)
      myTable.deleteRow(eTR.rowIndex)
      localStorage.setItem('dataArr', JSON.stringify(dataArr))
      resetForm()
      rowsInfo.last_no = dataArr.reduce((mx,{no})=>Math.max(mx,no),0)
      } 
  } }
#myTable {
  table-layout : fixed;  /* one of the Boostrap always missing... */
  }
#myTable tbody tr.selected {
  background-color : darkblue;
  color            : whitesmoke;
  }
#myTable tbody tr:hover {
  background-color : lightblue; 
  cursor           : pointer; 
  }
#myTable tbody tr.selected:hover {
  background-color : #1c1ce0; 
  }
#myTable tbody td:nth-of-type(5) div { 
  max-height    : 1.2em;  /* no multilines displaying */
  white-space   : pre;
  overflow      : hidden;
  } 
#myTable th:nth-of-type(1), 
#myTable td:nth-of-type(1),
#myTable th:nth-of-type(6), 
#myTable td:nth-of-type(6) { 
  width      : 4em;
  text-align : center;
  }
#myTable tbody td:nth-of-type(6):hover { 
  color : red;
  }
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
      integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" 
      crossorigin="anonymous">

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.13.0/css/all.css" >

<!-- Registration Form -->
<div class="container w-50 mt-3 shadow p-3 mb-5 bg-white rounded">
  <div class="p-3">
      <h1 class="mb-4">Registration Form</h1>
        <form class="task-form" name="my-form" autocomplete="off">
          <input type="hidden" name="no" id="no" value=""> 
          <label for="inputNL" class="form-label">Nama Lengkap</label>
          <input type="text" id="inputNL" name="inputNL" class="form-control mb-2" placeholder="Nama Lengkap">
          <label for="inputJK"class="form-label">Jenis Kelamin</label>
          <select class="form-select mb-2" id="inputJK" name="inputJK">
            <option value="Pria">Pria</option>
            <option value="Wanita">Wanita</option>
          </select>            
          <label for="inputNH" class="form-label">No HP</label>
          <input type="rowsInfo.last_no" id="inputNH" name="inputNH" class="form-control mb-2" placeholder="No HP">
          <label for="inputA" class="form-label">Alamat</label>
          <textarea id="inputA" name="inputA" class="form-control mb-2" style="min-width: 100%" placeholder="Alamat"></textarea>
          <input type="submit" value="Submit" class="btn btn-primary btn-md my-3">
        </form>
  </div>
</div>
<!-- Table -->
<div class="container mt-3 shadow p-3 mb-5 bg-white rounded">
  <div class="p-3">
    <table class="table" id="myTable">
      <thead>
          <th scope="col">#</th>
          <th scope="col">Nama Lengkap</th>
          <th scope="col">Jenis Kelamin</th>
          <th scope="col">No HP</th>
          <th scope="col">Alamat</th>
          <th scope="col">Aksi</th>
      </thead>
      <tbody> </tbody>
    </table>
  </div>      
</div>
localStorage object is considered has insecure into SO snippet

PS: I use exclusively Whitesmiths style

Upvotes: 1

Mister Jojo
Mister Jojo

Reputation: 22265

do something like that...

const 
  myForm       = document.forms['my-form']  // unique reference for ALL form's elements
, myTableTBody = document.querySelector('#myTable tbody')
, dataNL       = JSON.parse(localStorage.getItem('dataNL') || '[]')
  ;

// init table
dataNL.forEach(row=>
  {
  let newRow = myTableTBody.insertRow()

  newRow.insertCell().textContent = row.no
  newRow.insertCell().textContent = row.inputNL
  newRow.insertCell().textContent = row.inputJK
  newRow.insertCell().textContent = row.inputNH
  newRow.insertCell().textContent = row.inputA
  newRow.insertCell().textContent = ''  
  })

myForm.onsubmit = e =>
  {
  e.preventDefault()  

// add entries into local storage :
  dataNL.push(Object.fromEntries(new FormData(myForm).entries()))
  localStorage.setItem('dataNL', JSON.stringify( dataNL ))

// insert new row 

  let newRow = myTableTBody.insertRow()

  newRow.insertCell().textContent = myForm.no.value
  newRow.insertCell().textContent = myForm.inputNL.value
  newRow.insertCell().textContent = myForm.inputJK.value
  newRow.insertCell().textContent = myForm.inputNH.value
  newRow.insertCell().textContent = myForm.inputA.value
  newRow.insertCell().textContent = ''                   // Action
  }

-> some help <-

Upvotes: 4

Related Questions