0

Hey I am trying to make a new row each time someone enters something into a form. Right now i only have it where the user can only do one row. Every time someone inputs something it clears the first row with the new input, but i want it to make a new row with the new information each time someone enters something new into the form.

HTML code below

<form id="form" method="post" action="toDoList.php">
                    <div class="form-row">
                          <div class="form-group col-md-4">
                            <label for="Date">Date</label>
                            <input type="date" name="Date"  class="form-control" id="Date" placeholder="MM/DD/YY">
                          </div>
                          <div class="form-group col-md-4">
                            <label for="To Do">To Do</label>
                            <input class="form-control" name="ToDo" id="To Do" placeholder="To Do">
                          </div>
                          <div class="form-group col-md-4">
                                <label for="Due On">Due On</label>
                                <input type="date"  class="form-control" name="DueOn" id="Due On" placeholder="MM/DD/YY">
                              </div>
                        <button type="submit" class="btn btn-primary text-right">Submit</button>
                    </div>
            </form>

PHP code below

$toDo = $_POST["ToDo"];
$date = $_POST["Date"];
$dueOn = $_POST["DueOn"];

$newDate = date("m-d-Y", strtotime($date));
$newDate2 = date("m-d-Y", strtotime($dueOn));




        echo "<table  id='table' class='table table-bordered table-dark'>";
        echo "<thead>";
        echo "<tr>";
        echo "<th scope='col'>#</th>";
        echo "<th scope='col'>Date</th>";
        echo "<th scope='col'>To Do</th>";
        echo "<th scope='col'>Due On</th>";
        echo "<th scope='col'>Completed</th>";
        echo "</tr>";
        echo "</thead>";
        echo "<tbody>";
        echo "<tr>";
        echo "<th scope='row'>1</th>";
        echo "<td>";
        echo $newDate;
        echo "</td>";
        echo "<td> $toDo </td>";
        echo "<td> $newDate2  </td>";
        echo "<td>";
        echo "<div class='form-check'>";
        echo "<input class='form-check-input' type='radio' name='Completed' id='exampleRadios1' value='option0'>";
        echo "<label id='labelYes' class='form-check-label' for='exampleRadios1'>Yes</label>";
        echo "</div>";
        echo "</td>";
        echo "</tr>";
wzrd
  • 25
  • 3
  • When you say just php and html, do you mean to exclude JavaScript and database? Without JavaScript, you’ll have to submit and redraw the page each time. Without a database or other permanent storage, you’ll lose the rows if you visit any other page. It’s possible to do with just php and html, but there will be no persistence. – Tim Morton Nov 15 '19 at 04:53
  • How would i do it with javacript? i dont have a database so its not possible to do it with a database yet. – wzrd Nov 15 '19 at 18:39
  • The javascript simply makes it more fluid, but it doesn't solve the persistence problem. That may require local storage, but I've not used it. I can show you how to get up to that point, but I'll have to do some more research on local storage. I'll put up an answer that will at least point in the right direction, when I'm able to get to it. – Tim Morton Nov 15 '19 at 20:24
  • Oops, I stand corrected. Local storage is accessed via javascript, and it looks *fairly* simple. That will make this an all-javascript solution, while I was thinking of how to do it in php. The php solution would work, but only as long as you don't navigate to a different page or close the browser... I'll try to show both... – Tim Morton Nov 15 '19 at 20:30
  • okay i can have it all on one page but im still not sure how to do it with javascript. – wzrd Nov 15 '19 at 21:29

2 Answers2

1

A PHP-only solution would lack persistence without a database. Therefore the first solution will only work as long as the browser does not navigate to another page or get closed.

A javascript solution can make use of the local storage feature of a browser. As such, the javascript solution never submits data back to the server, but rather talks to local storage.

PHP Example

The thing that makes this work is the usage of arrays in the inputs. For example, if you had

Date      To Do   Due On
10/1/2019 Task 1  10/2/2019
10/1/2019 Task 2  10/3/2019

then $_POST['row'] will look like this:

$_POST = array (
  'row' => array(
    [0] => array(
      'date' => '10/1/2019',
      'todo' => 'Task 1',
      'duedate' => '10/2/2019'
      ),
    [1] => array(
      'date' => '10/1/2019',
      'todo' => 'Task 2',
      'duedate' => '10/3/2019'
      ),
    )
  )

The example script would look something like:

<?php
// always start with php, don't output any html until php stuff is all done.

// initialize variables
$tableRows = array();


// work with user input
if(isset($_POST['row'])) {

  // normally would save things to database, but
  // since there's no database, we'll just take the data and stuff it back into the page

  $row = $_POST['row'];    // for ease of typing
  settype($row, 'array');  // just to be sure it's an array

  foreach($row as $r) {

    // if the checkbox is not checked, add the submitted row to the new list
    if(!isset($r['completed'])) {

      $tableRows[] = $row;
    }
  }

  // normally would redirect to self or another page
  // header('Location: /');
}

// normally would do any other logic here


// now that PHP processing is finished, present the view (HTML)
?>
<html>
  <head>
    <title>ToDo List</title>
  </head>
  <body>
    <form method="post">
      <table  id="table" class="table table-bordered table-dark">
        <thead>
          <tr>
            <th scope="col">#</th>
            <th scope="col">Date</th>
            <th scope="col">To Do</th>
            <th scope="col">Due On</th>
            <th scope="col">Completed</th>
          </tr>
        </thead>
        <tbody>
          <?php foreach($tableRows as $index=>$row): ?>
          <tr>
            <th scope="row"><?= $index ?></th>
            <td><input type="text" name="row[<?=$index?>][date]"    value="<?= $row[$index]['date']  ?>"></td>
            <td><input type="text" name="row[<?=$index?>][todo]"    value="<?= $row[$index]['todo']     ?>"></td>
            <td><input type="text" name="row[<?=$index?>][duedate]" value="<?= $row[$index]['due date'] ?>"></td>
            <td>
              <div class="form-check">
                <input class="form-check-input" type="checkbox" name="row[<?=$index?>][completed]" id="completed-<?=$index?>" value="task_completed">
                <label id="labelYes" class="form-check-label" for="completed-<?=$index?>">Yes</label>
              </div>
            </td>
          </tr>
          <?php endforeach; ?>
        </tbody>
      </table>

      <div class="form-row">
      <div class="form-group col-md-4">
        <label for="Date">Date</label>
        <input type="date" name="row[][date]"  class="form-control" id="Date" placeholder="MM/DD/YY">
      </div>
      <div class="form-group col-md-4">
        <label for="To Do">To Do</label>
        <input class="form-control" name="row[][todo]" id="To Do" placeholder="To Do">
      </div>
      <div class="form-group col-md-4">
        <label for="Due On">Due On</label>
        <input type="date"  class="form-control" name="row[][duedate]" id="Due On" placeholder="MM/DD/YY">
      </div>
      <button type="submit" class="btn btn-primary text-right">Submit</button>
      </div>
    </form>
  </body>
</html>

Javascript Example

I took this on as a challenge to use Local Storage, as I haven't used it before.

<html>
  <head>
    <title>ToDo List</title>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  </head>
  <body>
    <div class="row"><div class="col-sm-12">
    <form method="post">
      <div>&nbsp;</div>
      <div class="form-row">
        <div class="form-group col-md-4">
          <label for="Date">Date</label>
          <input type="date" id="date-enter"  class="form-control" placeholder="MM/DD/YY" value="" required>
        </div>
        <div class="form-group col-md-4">
          <label for="To Do">To Do</label>
          <input class="form-control" id="todo-enter" placeholder="To Do" value="" required>
        </div>
        <div class="form-group col-md-4">
          <label for="Due On">Due On</label>
          <input type="date"  class="form-control" id="due-enter" placeholder="MM/DD/YY" value="" required>
        </div>
        <button type="submit" class="btn btn-primary text-right" id="add-row">Submit</button>
      </div>
      <div>&nbsp;</div>

      <table  id="table" class="table table-bordered table-dark">
        <thead>
          <tr>
            <th scope="col">#</th>
            <th scope="col">Date</th>
            <th scope="col">To Do</th>
            <th scope="col">Due On</th>
            <th scope="col">Completed</th>
          </tr>
        </thead>
        <tbody id="table-tbody">
        <script type="text/template" data-template="table-template">
          <tr>
            <th scope="row">${index}</th>
            <td>${date}</td>
            <td>${todo}</td>
            <td>${due}</td>
            <td>
              <!-- 
                <input type="date" id="date-row-${index}" value="${date}"> 
                <input type="text" id="todo-row-${index}" value="${todo}">
                <input type="date" id="due-row-${index}" value="${due}">
              -->
              <div class="form-check">
                <input class="form-check-input" type="checkbox" id="row-completed-${index}" data-index="${index}">
                <label class="form-check-label" for="row-completed-${index}">Yes</label>
              </div>
            </td>
          </tr>
        </script>
        </tbody>
      </table>

    </form>
  </div></div>
  <script
  src="https://code.jquery.com/jquery-3.4.1.min.js"
  integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
  crossorigin="anonymous"></script>


  <script>
  // ensures DOM is loaded first
  $(document).ready(function() {

    // initialize "global" variables.  These are available at all child levels. (i.e., in functions)
    var todoData = [];  // this is all your data as a javascript array
    var template = $('script[data-template="table-template"]').text().split(/\$\{(.+?)\}/g);

    // first, get anything previously stored and write table rows
    todoData = getFromStorage();
    writeTable(todoData);


    // begin "listeners" which wait for events like form submission and click on the "completed" checkbox
    $('form').on('submit', function(e) {
      e.preventDefault();  // html5 validation requires the form be submitted, but this prevents it from following through on the submission.
      addRow();
    });

    // note, this listener must be anchored to document, since it is monitoring DOM elements that are dynamic
    $(document).on('click', '.form-check-input', function() {
      var i = $(this).data("index");
      console.log(i);
      if(confirm("Delete this row?")) {
        // delete this row
        todoData.splice(i-1, 1); // array starts at 0, we start at 1...

        saveToLocalStorage(todoData);
        writeTable(todoData);
      }
    });


    // begin functions that do all the work
    function addRow() {

      var data = {
        // index: index,
        date: $('#date-enter').val(),
        todo: $('#todo-enter').val(),
        due: $('#due-enter').val()
      };

      clearForm();

      todoData.push(data);

      saveToLocalStorage(todoData);

      var fromStorage = getFromStorage();
      writeTable(fromStorage);
    }

    function clearForm() {

      $('#date-enter').val('');
      $('#todo-enter').val('');
      $('#due-enter').val('');
    }

    // store the entire array, not just a single row
    function saveToLocalStorage(data) {

      localStorage.clear();
      console.log('storing data in local storage:');
      console.log(data);
      localStorage.setItem('todoList', JSON.stringify(data));
    }

    function getFromStorage() {
      
      // addRow is intended to take json values from ajax.  It will support multiple rows.
      // this is test data:
      // var data = [
      //   {date: '2019-01-01',todo: 'Start the year', due: '2019-12-31'},
      //   {date: '2019-12-25',todo: 'Celebrate Christmas',due: '2019-12-25'}
      // ];

      // get data from local storage
      data = JSON.parse(localStorage.getItem('todoList')); 

      // todoData = data; // using a "global" variable is probably not good practice.
      return data;
    }

    function addIndexToData(data) {

       var index=1;  
       // takes each row of data, and adds "index" property to it, giving it the value of index and then incrementing index
      data.map(function(row) {
        row.index = index++;
        return row;
      });

      return data;
   }

    // html template rendering function. see https://stackoverflow.com/a/39065147/2129574
    function render(props) {
      return function(tok, i) { return (i % 2) ? props[tok] : tok; };
    }

    // html template rendering function. see https://stackoverflow.com/a/39065147/2129574
    function writeTable(data) {

      // if not an array, stop before things puke.
      if(!Array.isArray(data)) { 
        console.log("data was not an array.  That just won't work.");
        console.log(data);
        return; 
      }

      data = addIndexToData(data);

      var trow = data.map(function(rows) {
        return template.map(render(rows)).join('');
      });

      // $('#table-tbody').append(trow);
      $('#table-tbody').html(trow);

    }
  }); 


    
  </script>
  </body>
</html>
Dharman
  • 30,962
  • 25
  • 85
  • 135
Tim Morton
  • 2,614
  • 1
  • 15
  • 23
0

You need to echo the data inside a hidden input so it can pass to the next page when you submit the form and then pull those rows again.