1

I am trying to create a delete button which will delete its parent div and everything inside it

function remove() {
  var $this = $(this).closest();
  //console.log($this)
  $this.remove();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="background-color: green;">
  <div>NAME</div>
  <div><button onclick="remove">Remove</button>
  </div>
</div>

However, whenever I press the button, nothing happens.

EDIT:

$(function() {
  $('button').click(function() {
    var $this = $(this).closest('.container');
    $this.remove();
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div>NAME 1</div>
  <div><button>Remove</button></div>
</div>
<div class="container">
  <div>NAME 2</div>
  <div><button>Remove 2</button></div>
</div>

Nothing happens and no errors occur.

EDIT 2:

This is my entire javascript:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js"></script>
<script type="text/javascript">
var csrftoken = Cookies.get('csrftoken');

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});
var suggested_students = $("#suggested_students");
var search_bar = $('#search_bar');

function clear(){
    suggested_students.empty(); 
    search_bar.val('');
}

search_bar.keyup(function () {

    var keyword = search_bar.val();
    if(keyword.length > 2){
        //console.log('hey')
        var url = window.location.pathname;
        $.ajax({
            method: 'GET',
            url: url,
            data: {
            'keyword': keyword,
            },
            dataType: 'json',
            success: function (data) {
                suggested_students.empty(); 
                var suggestions = data.students;
                for(i = 0; i< suggestions.length; i++){
                    var current_student = suggestions[i];
                    var div = $("<a href='#'><div/></a>");
                    div.data("name", current_student[0]);
                    div.data("id", current_student[1]);
                    div.html(current_student[0] + "<br/>");
                    div.on("click", moveProfile);
                    div.css({"background-color": "green"});
                    suggested_students.append(div);
                }
            }
            })
        }else if(keyword.length == 0){
            clear()

        }
    })

var students_to_add = $("#students_to_add")

function moveProfile(){
    var $this = $(this);
    var studentID = $this.data("id");
    var studentName = $this.data("name");
    var div = $("<div/>");
    div.data('id', studentID);
    div.data('name', studentName);
    div.html("<div>" + studentName +"</div><div><button>Remove</button></div>");
    div.css({"background-color": "green"});
    div.addClass("container")
    students_to_add.append(div);    
    clear()
}


$(function() {
    $('button').click(function() {
      var $this = $(this).closest('.container');
      $this.remove();
    });
  });


</script>

And this is the entire HTML:

<div>
    <label>Set Name: </label>
    <input type="text" class="class_name" id='class_name'/>
</div>
<br>

<div class='student_search_bar'>
    <label for='search_bar'>Search for Students: </label>
    <input type="text" class="student_search_bar_bar" id='search_bar'/>   
</div>
<br>
<div id='suggested_students'>

</div>

<div id='students_to_add'>
    <label>Students to add: </label>

</div>

I have a function which gets a list from an AJAX call and make it into multiple divs like so:

<div class="container">
  <div>NAME</div>
  <div>
    <button>Remove</button>
  </div>
</div>

My Javascript is below my html, and is all in the same file.

When I run the code that has been suggested by Rory McCrossan, I get no errors in the console, and when I have used a console.log to see if the function is called, nothing is printed.

wtreston
  • 1,051
  • 12
  • 28
  • Also look at the `.parent()` method https://api.jquery.com/parent/ – JConstantine Jan 05 '18 at 08:54
  • Only button container or whole block? – Hanif Jan 05 '18 at 08:54
  • Do you mean the div with the `background-color: green`? – dork Jan 05 '18 at 08:54
  • possible duplicate of https://stackoverflow.com/questions/6647736/how-to-delete-parent-element-using-jquery#6647788 – Qiqo Jan 05 '18 at 08:54
  • @dork yes i am trying to do that – wtreston Jan 05 '18 at 08:57
  • Well, first, `closest` is going to return an empty jQuery object since you don't have a selector. Second, `this` in your function is going to refer to the `window` object; you have to bind the button to the function: `onclick=remove.bind(this)()`. And third, like my second point, you need to call the function, not just assign it to the onclick. – dork Jan 05 '18 at 09:05
  • Why don't you add classes for more specific selectors? – UncaughtTypeError Jan 05 '18 at 09:10
  • *will delete its parent div*` the `button` is inside it's own `div`, so would not hit the 'green' div even if you used `.parent()` (or `.closest("div")`). – freedomn-m Jan 05 '18 at 09:54
  • I've converted your EDIT code to a snippet - run the snippet and you'll see it works fine. Therefore, there is some other issue that you've not included in the question. – freedomn-m Jan 05 '18 at 09:58
  • @freedomn-m I have posted the entire file in the hopes that you can fix it – wtreston Jan 05 '18 at 10:05
  • Possible duplicate of [Event binding on dynamically created elements?](https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) – freedomn-m Jan 05 '18 at 10:27
  • And there's the issue. *gets a list from an AJAX call and make it into multiple divs* - your event binding occurs before the elements exist therefore there is nothing to bind them against. You need to either add the binding to the js code that adds the divs or use event delegation: https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements – freedomn-m Jan 05 '18 at 10:28

4 Answers4

3

When using on* event attributes, the this reference will be the window, not the clicked element. Also, closest() requires a selector.

To fix the problem, attach an unobtrusive event handler to the button instead. As you're dynamically appending the button elements you'll need to use a delegated event handler, like this:

$(function() {
  $('#students_to_add').on('click', 'button', function() {
    var $this = $(this).closest('.container');
    $this.remove();
  });
});
.container {
  background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="students_to_add">
  <div class="container">
    <div>NAME</div>
    <div>
      <button>Remove</button>
    </div>
  </div>
  <div class="container">
    <div>NAME</div>
    <div>
      <button>Remove</button>
    </div>
  </div>
  <div class="container">
    <div>NAME</div>
    <div>
      <button>Remove</button>
    </div>
  </div>
</div>
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • Hi. There will be more than one instance of the html above, each with their own delete button. I dont think this code will work in that case – wtreston Jan 05 '18 at 09:02
  • 1
    This code is specifically designed for that situation. I've updated the HTML in there to show you it working. – Rory McCrossan Jan 05 '18 at 09:10
  • @wtreston If you use the `.container` class for each instance it should work as intended. – UncaughtTypeError Jan 05 '18 at 09:11
  • I am trying this and when I press the button nothing happens. I dont get any errors and I have copy pasted the code to first see if it works – wtreston Jan 05 '18 at 09:15
  • I added a console.log line to the javascript to see if it was being called but it isnt. – wtreston Jan 05 '18 at 09:24
  • Are you sure you copy+pasted it properly? You can see it works fine from the snippet above. Note that you need to place the jQuery code *after* you include jQuery in the page. Check the console for errors – Rory McCrossan Jan 05 '18 at 09:25
  • @RoryMcCrossan I updated my original post with the code that I now have. – wtreston Jan 05 '18 at 09:32
  • @Philipp It works on there for me too, but when I try run it it isnt working – wtreston Jan 05 '18 at 09:43
  • @wtreston you put the script inside script tags or an external javascript file? you checked the error console? you checked, the script is actually loaded? – Philipp Jan 05 '18 at 09:44
  • @Philipp Inside script tags, not in an external file. No errors in the console and the script is loaded when i go to inspect the page – wtreston Jan 05 '18 at 09:46
  • I copy pasted everything I have into a jsfiddle and it works perfectly however when run locally it doesnt – wtreston Jan 05 '18 at 09:53
  • Here's a fiddle with a full sample. This is what your HTML should look like: https://jsfiddle.net/h4vjx1r3/ – Rory McCrossan Jan 05 '18 at 09:55
  • Does the script have to be above the html? – wtreston Jan 05 '18 at 09:59
  • No, it could be just before the `

    ` tag too, if you prefer.

    – Rory McCrossan Jan 05 '18 at 10:00
  • I posted my entire html file. maybe there is a problem elsewhere – wtreston Jan 05 '18 at 10:12
  • Yep, as @freedomn-m has said the fact you're dynamically creating the HTML elements makes a ***big*** difference to how you hook event handlers. You need to use a delegated event handler. I updated my answer to show you how – Rory McCrossan Jan 05 '18 at 10:34
1

You could change this code to something like this

<div id="box" style="background-color: green;">
    <div>NAME</div>
    <div><button data-remove="#box">Remove</button>
    </div>
</div>

and with the following code, you have an generic approach for all elements with an data-remove attribute

$(function() {
    $('[data-remove]').on('click', function() {
        $($(this).data('remove')).remove();
    });
});

If you want to use closest, you should add proper classes to identify the elementss to be handled.

<div class="box" style="background-color: green;">
    <div>NAME</div>
    <div><button class="close-box">Remove</button>
    </div>
</div>

with this script

$(function() {
    $('.close-box').on('click', function() {
        $(this).closest('.box').remove();
    });
});
Philipp
  • 15,377
  • 4
  • 35
  • 52
0

You need to pass selector in closest()

Html

<button onclick="remove(this)">Remove</button>
                   ----^^^^^^---- here

Javascript

function remove(ele){
    var $this = $(ele).closest('div');
    //console.log($this)
    $this.remove();

}

However, this will remove the closest div from the button. I am not sure which div you want to remove. You can give an id to a div you want to delete and use that instead.

eg:

<div style="background-color: green;" id="some-id">

var $this = $(ele).closest('#some-id');

Better way:

$('button').click(function() {
  var $this = $(this).closest('div');
  $this.remove();
}); 
bipen
  • 36,319
  • 9
  • 49
  • 62
0

Give proper brackets for the function as follows.

<div><button onclick="remove()">Remove</button>
kmg
  • 499
  • 3
  • 16