Search code examples
javascriptjqueryjquery-uiappendappendchild

jQuery: Can't select a new element after append


I created a structure to represent the UI Tree using jQuery. I added the ability to add a new element at any level (The "add new" button is activated when you select a level for adding).

But in my example, I can not add a new element to the newly created element. I tried different ways, but it does not work.

I'll be happy for the tips on how I can fix this problem

$(function() {

  const newElement = $('#new-element');
  let targetButton;

  function indexOfChildren() {
    $('li').prepend(function() {
      let countOfChildren = $(this).children().find(">li").length;
      let targetSpan = $(this).find('button>:first-child');
      targetSpan.text(countOfChildren);
    });
  };
  indexOfChildren();

  $('li>button').on('focus', function(e) {
    targetButton = $(this);
    newElement.prop("disabled", false);
  });

  $('[name="new-button"]').on('click', function(e) {
    targetButton = $(this);
    newElement.prop("disabled", false);
  });


  newElement.click(function() {
    let name = prompt("Please enter name of new element");
    let parentTargetButton = targetButton.closest('li');
    let indexTargetSpan = parseInt(targetButton.find(':first-child').text());
    if (name != null) {
      if (indexTargetSpan == 0) {
        parentTargetButton.append('<ul><li><button class="btn mb-3 mt-1" name="new-button">' + name + '<span></span></button></li></ul>');
      } else {
        parentTargetButton.children('ul').append('<li><button class="btn mb-3 mt-1" name="new-button">' + name + ' <span></span></button></li>');
      }
    }
    indexOfChildren();
    targetButton.focus();
  });

});
body {
  background-color: #f5f6f8;
}

.main-content {
  background: #fff;
  box-shadow: 0 5px 20px 0 #c8d2dd6e;
  -webkit-box-shadow: 0 5px 20px 0 #c8d2dd6e;
  border-radius: 5px;
}

.top-level {
  border-bottom: 1px solid #dadee7;
}

ul {
  list-style-type: none;
}

ul>li>ul {
  border-left: 1px solid #eee;
  margin-left: 60px;
}

ul>li>ul>li:before {
  border-left: 1px solid;
}

#new-element {
  background-color: #33b5ff;
  color: #fff;
  border-radius: 40px;
}

.main-content .btn {
  box-sizing: content-box;
  width: 140px;
  padding: 14px;
  text-align: left;
  background-color: #f5f6f8;
  border-radius: 7px;
}

span {
  float: right;
  color: #fff;
  line-height: 1.4;
  border-radius: 0.8em;
  -moz-border-radius: 0.8em;
  -webkit-border-radius: 01em;
  text-align: center;
  font-size: 0.9em;
  width: 1.4em;
  background-color: #33b5ff;
}

.btn:focus,
.btn:hover,
#new-element {
  -webkit-box-shadow: 0 5px 25px 0 #9dabbb69;
  */ box-shadow: 0 5px 25px 0 #9dabbb69;
}

.main-content .btn:focus {
  color: #fff;
  background-color: #0095ff!important;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body>
  <div class="container project-item my-3 pt-5">
    <div class="row top-level pb-4">
      <h3 class="col-sm-9 pl-0">New Project</h3>
      <div class="col-sm-3 pr-0">
        <button type="button" class="btn float-right" id="new-element" disabled>+ Add new element</button>
      </div>
    </div>
  </div>
  <div class="container main-content pt-5 mt-5 pb-5">
    <ul>
      <li>
        <button class="btn mb-3 mt-1">Project <span></span></button>
        <ul>
          <li>
            <button class="btn mb-3 mt-1">Web Design <span></span></button>

            <ul>
              <li>
                <button class="btn mb-3 mt-1">CSS <span></span></button>
              </li>
              <li>
                <button class="btn mb-3 mt-1">HTML <span></span></button>
                <ul>
                  <li>
                    <button class="btn mb-3 mt-1">HTML <span></span></button>
                  </li>
                  <li>
                    <button class="btn mb-3 mt-1">XHTML <span></span></button>
                  </li>
                </ul>
              </li>
            </ul>

          </li>
        </ul>
      </li>
    </ul>

  </div>

</body>


Solution

  • You can bind the .on event to the already existing parent element.

    $('li').on('focus', 'button', function(e) {
      targetButton = $(this);
      newElement.prop("disabled", false);
    });
    

    $(function() {
    
      const newElement = $('#new-element');
      let targetButton;
    
      function indexOfChildren() {
        $('li').prepend(function() {
          let countOfChildren = $(this).children().find(">li").length;
          let targetSpan = $(this).find('button>:first-child');
          targetSpan.text(countOfChildren);
        });
      };
      indexOfChildren();
    
      $('li').on('focus', 'button', function(e) {
        targetButton = $(this);
        newElement.prop("disabled", false);
      });
    
      $('[name="new-button"]').on('click', function(e) {
        targetButton = $(this);
        newElement.prop("disabled", false);
      });
    
    
      newElement.click(function() {
        let name = prompt("Please enter name of new element");
        let parentTargetButton = targetButton.closest('li');
        let indexTargetSpan = parseInt(targetButton.find(':first-child').text());
        if (name != null) {
          if (indexTargetSpan == 0) {
            parentTargetButton.append('<ul><li><button class="btn mb-3 mt-1" name="new-button">' + name + '<span></span></button></li></ul>');
          } else {
            parentTargetButton.children('ul').append('<li><button class="btn mb-3 mt-1" name="new-button">' + name + ' <span></span></button></li>');
          }
        }
        indexOfChildren();
        targetButton.focus();
      });
    
    });
    body {
      background-color: #f5f6f8;
    }
    
    .main-content {
      background: #fff;
      box-shadow: 0 5px 20px 0 #c8d2dd6e;
      -webkit-box-shadow: 0 5px 20px 0 #c8d2dd6e;
      border-radius: 5px;
    }
    
    .top-level {
      border-bottom: 1px solid #dadee7;
    }
    
    ul {
      list-style-type: none;
    }
    
    ul>li>ul {
      border-left: 1px solid #eee;
      margin-left: 60px;
    }
    
    ul>li>ul>li:before {
      border-left: 1px solid;
    }
    
    #new-element {
      background-color: #33b5ff;
      color: #fff;
      border-radius: 40px;
    }
    
    .main-content .btn {
      box-sizing: content-box;
      width: 140px;
      padding: 14px;
      text-align: left;
      background-color: #f5f6f8;
      border-radius: 7px;
    }
    
    span {
      float: right;
      color: #fff;
      line-height: 1.4;
      border-radius: 0.8em;
      -moz-border-radius: 0.8em;
      -webkit-border-radius: 01em;
      text-align: center;
      font-size: 0.9em;
      width: 1.4em;
      background-color: #33b5ff;
    }
    
    .btn:focus,
    .btn:hover,
    #new-element {
      -webkit-box-shadow: 0 5px 25px 0 #9dabbb69;
      */ box-shadow: 0 5px 25px 0 #9dabbb69;
    }
    
    .main-content .btn:focus {
      color: #fff;
      background-color: #0095ff!important;
    }
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <body>
      <div class="container project-item my-3 pt-5">
        <div class="row top-level pb-4">
          <h3 class="col-sm-9 pl-0">New Project</h3>
          <div class="col-sm-3 pr-0">
            <button type="button" class="btn float-right" id="new-element" disabled>+ Add new element</button>
          </div>
        </div>
      </div>
      <div class="container main-content pt-5 mt-5 pb-5">
        <ul>
          <li>
            <button class="btn mb-3 mt-1">Project <span></span></button>
            <ul>
              <li>
                <button class="btn mb-3 mt-1">Web Design <span></span></button>
    
                <ul>
                  <li>
                    <button class="btn mb-3 mt-1">CSS <span></span></button>
                  </li>
                  <li>
                    <button class="btn mb-3 mt-1">HTML <span></span></button>
                    <ul>
                      <li>
                        <button class="btn mb-3 mt-1">HTML <span></span></button>
                      </li>
                      <li>
                        <button class="btn mb-3 mt-1">XHTML <span></span></button>
                      </li>
                    </ul>
                  </li>
                </ul>
    
              </li>
            </ul>
          </li>
        </ul>
    
      </div>
    
    </body>