Zhuo
Zhuo

Reputation: 99

Hide/show child element onClick

I am building a "edit profile" page.

Here is what I want to do:

  1. In each section, the employer will be shown and the edit form will be hidden.
  2. When I click the "edit employer" button, the edit form will be shown and the employer will be hidden.

Here is what I did using jQuery. It does not work when I click on the "edit employer" button. I do not know why this does not work.

<!DOCTYPE html>
<html>
    <head>
        <script
    src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    </head>

    <body>
        <div class="edit">
            <form class="editForm">
                employer: <input type="text" value="Citigroup" />
            </form>
            <div class="contents">Employer: Citigroup</div>
            <button class="editButton">Edit Employer</button>
        </div>

        <script>
            $('div.edit').each(function(i) {
                $(this).children('.editForm').hide();
            })
            $('div.edit').each(function() {
                $(this).children('.editButton').click(function() {
                    $(this).children('.editForm').show();
                    $(this).children('.contents').hide();
                });
            })
        </script>
    </body>
</html>

Upvotes: 0

Views: 2740

Answers (3)

George Antonakos
George Antonakos

Reputation: 748

The $(this) inside the click function contains the local instance of the $(this).children('.editButton'). For that reason your code is not finding any .editForm elements.

For this to work you could do something like this:

<script>
    $('div.edit').each(function(i) {
        $(this).children('.editForm').hide();
    })
    $('div.edit').each(function() {
        var $this = $(this);
        $(this).children('.editButton').click(function() {
            $this.children('.editForm').show();
            $this.children('.contents').hide();
        });
    })
</script>

If I may I would improve the code with some more changes:

<script>
    $('.edit .editForm').hide(); // this will hide all instances of .editForm
    $('.edit .editButton').click(function() { //assign 1 handler for all cases
       $(this).siblings('.editForm').show(); // show the sibling edit form
       $(this).siblings('.contents').hide(); // hide the sibling contents element
    });
</script>

Reference: Sibling Selector: https://api.jquery.com/siblings/#siblings-selector

Upvotes: 2

ntgCleaner
ntgCleaner

Reputation: 5985

You don't need to use .each() at all. Just do an .click() event on the class of .editButton and use this to find its parent. If you want to make a toggle, you're going to have to make use of a new class or something of that nature to make a conditional statement off of.

//This will hide *ANY* .editForm elements
$('.editForm').hide();

//This will fire off of *ANY* editButton clicks.
$('.editButton').click(function() {
    var form = $(this).closest('.edit');             //Get the wrapper
    if(form.hasClass('open')) {                      //Check to see if it is open or not
        form.removeClass('open').addClass('close');  //Toggle Classes
        form.find('.editForm').show();
        form.find('.contents').hide();
    } else {
        form.removeClass('close').addClass('open');
        form.find('.editForm').hide();
        form.find('.contents').show();
    }
});

I like to use closest and find more than parent and children (respectively). They can go 1-many layers up or down and search the hierarchy for whatever you're looking for, rather than parent and children going up or down a single layer.

If you are inserting your .edit form after the DOM loads, you're going to need to bind your click event to the document

$(document).on('click', '.editButton', function() {
    var form = $(this).closest('.edit');
    form.find('.editForm').hide();
    form.find('.contents').show();
});

Upvotes: 0

user5734311
user5734311

Reputation:

The problem is the this inside the click handler referring to the button, not the div.edit. Here's one way to fix this:

$('div.edit').each(function(i) {
  $(this).children('.editForm').hide();
});
$('div.edit').each(function() {
  var $self = $(this);
  $(this).children('.editButton').click(function() {
    $self.children('.editForm').show();
    $self.children('.contents').hide();
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="edit">
  <form class="editForm">
    employer:
    <input type="text" value="Citigroup" />
  </form>
  <div class="contents">Employer: Citigroup</div>
  <button class="editButton">Edit Employer</button>
</div>

Upvotes: 0

Related Questions