evanparial
evanparial

Reputation: 45

How do I delete only one row of appended information in a table using jQuery?

I am trying to make a "My Favorite Movies" list page where users can add and rate movies. This program should include:

1) a form where you can add to the list and rate it

2) a table of all the things you've added

3) delete button for each row of the table that lets you remove elements from the list (what i'm having trouble on)

Instead of deleting only one row, it deletes every appended movie/rating in the table. Also if you click anywhere else, it deletes everything as well.

4) bonus: sort feature, so i can sort entries in the table by the their title or their rating.

example here: rithm school example

$(function() {
  $('#addMovieButton').click(function() {
    var addToTitle = $('#title').val();
    $('#tableTitle').append('<tr><td>' + addToTitle + '</td></tr>');

    var addToRating = $("#rating").val();
    $('#tableRating').append('<tr><td>' + addToRating + '</td></tr>');

    $('#tableDelete').append('<tr><td><input type="button" value="Delete All"</tr></td>');

    $('#tableRow').on('click', function() {
      $('#tableTitle').last().children().remove();
      $('#tableRating').last().children().remove();
      $('#tableDelete').last().children().remove();


    });
  });
});
h1 {
  text-align: center;
}

table {
  width: 100%;
  border-radius: 10px;
}

table,
td {
  border: 1px solid black;
  padding: 15px;
}

th {
  height: 50px;
  text-align: center;
}

td {
  text-align: center;
}

body {
  font-family: helvetica;
}

form {
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<form>
  <label><b>Title</b></label>
  <input id="title" type="text" value="Movie Title">

  <label><b>Rating</b></label>
  <input id="rating" type="text" value="Rate The Movie from 0 to 10">

  <button type='button' id="addMovieButton">Add Movie</button>
</form>

<table>
  <tr id="tableRow">
    <th id="tableTitle">Title</th>
    <th id="tableRating">Rating</th>
    <th id="tableDelete">Delete</th>
  </tr>
</table>

Upvotes: 1

Views: 609

Answers (2)

zer00ne
zer00ne

Reputation: 43880

<table> Structure

The structure of the appended "row" are not valid HTML. A <table> will have at least one <tbody>. If the user doesn't add it the browser will. Although most methods, function, and properties will treat the <table> as the direct parent of <tr>, there are some advantages to targeting <tbody> instead. If there's a <thead> then targeting the <tbody> can free you from extra steps trying to avoid the <th>.

Keep these rules in mind when structuring a <table>

  • <tbody> can only have <tr> as children (direct descendants)
  • <tr> can only have <td> and <th> as children
  • <td> and <th> can have anything as descendants.

Make sure rows are structured like so:

<tr><td</td>...<td></td></tr>

Add row to <table> or <tbody>


Demo

The following demo has detailed comments within the HTML, and CSS, as well as step by step details commented in the JavaScript

$(function() {

  /*
  Bind the <form> to the 'submit', 'click', and 'change' events.
  Pass the Event Object thru
  */
  $('form').on('submit click change', function(event) {

    // Reference the type of event
    let eType = event.type;

    // if the 'submit' event was triggered...
    if (eType === 'submit') {

      // Stop the <form> from sending data to a server and resetting
      event.preventDefault();

      // Get the values of the <input>
      let name = $('.title').val();
      let rate = $('.rating').val();

      // Declare a htmlString using a Template Literal 
      const row = `
        <tr><td>${name}</td>
        <td>${rate}</td>
        <td><input class='sel' type='checkbox'>
        </td></tr>`;

      // Render the htmlString as the last child of the <tbody>
      $('.data').append(row);

      // Reset <form>
      $(this).trigger('reset');

      // ...otherwise if the 'click' event triggered...
    } else if (eType === 'click') {

      // ...and the clicked tag has class 'del'...
      if ($(event.target).hasClass('del')) {

        /*
        Collect all checked <input class='sel'>
        then on .each() one...
        */
        $('.sel:checked').each(function(i) {

          /*
          Get the ancestor <tr> of the current .sel
          and remove it
          */
          $(this).closest('tr').remove();
        });

        // Reset the <form>
        $('form').trigger('reset');
      }
      
      // ...otherwise if the 'change' event was triggered...
    } else if (eType === 'change') {

      // ...and the changed tag id is 'all'...
      if (event.target.id === 'all') {

        // Check if #all is checked or not
        let allChk = $('#all').is(':checked');

        // Loop thru each() <input class='sel'>...
        $('.sel').each(function(i) {

          /* 
          and check current .sel if #all is checked
          or uncheck current .sel if #all is NOT checked
          */
          $(this).prop('checked', allChk);
        });
      }
    }
    // Stop any events from bubbling any further up the event chain
    event.stopPropagation();
  });
});
:root {
  font: 400 3vw/1.2 Arial;
}

form {
  text-align: center;
}

table {
  width: 100%;
  border-radius: 10px;
  table-layout: fixed;
  margin: 12px auto
}

table,
td {
  border: 1px solid black;
  padding: 15px;
}

th {
  height: 30px;
  width: 20%;
}

th:first-of-type {
  width: 60%;
}

td {
  text-align: center;
}

button,
input,
label {
  display: inline-block;
  font-size: initial;
}

.all {
  font-weight: 400;
  padding: 3px 6px;
  border: 1.5px inset rgba(0, 28, 255, 0.3);
  margin-top: 3px;
}

.all::after {
  content: 'Selected'
}

/*
When input@all is :checked the label.all that follows
#all will change 
the content of its pseudo-element from 'Selected' to 'All'
*/
#all:checked+.all::after {
  content: 'All'
}

button:hover {
  cursor: pointer;
  outline: 3px outset rgba(0, 28, 255, 0.4);
  color: rgba(0, 28, 255, 0.6);
}

.all:hover {
  cursor: pointer;
  color: rgba(0, 28, 255, 0.8);
  background: rgba(0, 28, 255, 0.2);
}

.rating {
  text-align: right;
  width: 4ch;
}

.title {
  padding-left: 5px;
  width: 27ch;
}

/*
The checkbox #all is not visible to user but is accessible through the label.all 
which it is synced with (see comments in HTML
*/
#all {
  display: none
}
<form>
  <label>Title</label>
  <!--
  The [required] attribute enables built-in form validation
  If the submit event is triggered 
  and either <input> is blank, the submit event is interrupted and 
  a tooltip will notify 
  user that the <input> cannot be empty
  -->
  <input class="title" type="text" placeholder="Pulp Fiction" required>

  <label>Rating</label>
  
  <!-- See previous comment -->
  <input class="rating" type="number" min='0' max='10' placeholder="10" required>
  <!--
  <button type='submit'> or <input type='submit'>
  or <button> within a <form> will trigger a submit event by default
  -->
  <button>Add Movie</button>
  <table>
    <thead>
      <tr>
        <th>Title</th>
        <th>Rating</th>
        <th>
          <button class='del' type='button'>Remove</button>
          <!--
          A <label> and a form control (ie <input>, <textarea>, <select>, etc) can be synced by
          matching the [for] attribute value to the form controls #id:
          1. <label for='XXX'>
          2. <input id='XXX'>
          When synced, clicking one will remotely click the other
          -->
          <input id='all' type='checkbox'>
          <label class='all' for='all'></label></th>
      </tr>
    </thead>
    <!--
    See post on <table> structure
    -->
    <tbody class='data'></tbody>
  </table>

</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Upvotes: 1

Zeinab_Ns
Zeinab_Ns

Reputation: 305

you've put all titles in a parent, and all rating in another parent ,and all delete buttons in another one . you should place the information about each row in a parent and then you can delete by row easily. (also you can add td,tbody it's just sample to showing the way)

$('#addMovieButton').click(function () {
                var addToTitle = $('#title').val();
                var addToRating = $("#rating").val();
                $('#table').append('<tr><th>' + addToTitle + '</th><th>' + addToRating + '</th><th><input type="button" value="Delete All" class="tableDelete"></th></tr>');


                $('.tableDelete').click(function () {
                    $(this).parents('tr').remove();
                    
                });

            });
        h1 {
  text-align: center;
}

table {
  width: 100%;
  border-radius: 10px;
}

table,
td {
  border: 1px solid black;
  padding: 15px;
}

th {
  height: 50px;
  text-align: center;
}

td {
  text-align: center;
}

body {
  font-family: helvetica;
}

form {
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
 <form>
        <label><b>Title</b></label>
        <input id="title" type="text" value="Movie Title">

        <label><b>Rating</b></label>
        <input id="rating" type="text" value="Rate The Movie from 0 to 10">

        <button type='button' id="addMovieButton">Add Movie</button>
    </form>

    <table id="table">
       
    </table>

Upvotes: 0

Related Questions