Implementing Dynamic Parent Node Manipulation with Button Clicks in JavaScript

I am currently working on dynamically creating an input field using the append child method along with add and delete buttons to form a tree-like structure. The goal is to be able to create child nodes with add and delete buttons upon clicking the add button. Additionally, clicking the add button within a child node should generate a sub-child node. While I have achieved this manually, I am now looking for a way to dynamically add child and sub-child nodes for any number of iterations using the append child method in JavaScript.

Furthermore, upon clicking the delete button, the parent node should be removed. How can I retrieve the dynamically generated ID of the parent node?

function add_div(){
      var div1 = document.createElement('ul');
      document.body.appendChild(div1);
      div1.className = 'ui-modal';
      div1.id = 'test-' + document.querySelectorAll('.ui-modal > .msg1').length;
      var  check = div1.id;

      var list = document.createElement('li');

      list.className = 'msg1';
      div1.appendChild(list);

      var input = document.createElement('input');
      list.appendChild(input);
      input.placeholder="parent";

      var button1 = document.createElement('button');
      list.appendChild(button1);

      var t1 = document.createTextNode("ADD");
      button1.appendChild(t1);

      button1.addEventListener("click", add_div2);


      var button2 = document.createElement('button');
      list.appendChild(button2);

      var t2 = document.createTextNode("DEL");
      button2.appendChild(t2);

      button2.addEventListener("click", remove_div);
    function add_div2(){
      var div2 = document.createElement('ul');
      div1.appendChild(div2);

      var lists = document.createElement('li');
      div2.appendChild(lists);
      div2.className = 'sub-div';

      div2.id = 'sub_test-' + document.querySelectorAll('.sub-div > .msg2').length;

      lists.className = 'msg2';
      div2.appendChild(lists);

      var inputs = document.createElement('input');
      lists.appendChild(inputs);
      inputs.placeholder="child";

      var button1s = document.createElement('button');
      lists.appendChild(button1s);

      var t1s = document.createTextNode("ADD");
      button1s.appendChild(t1s);

      button1s.addEventListener("click", add_div3);


      var button2s = document.createElement('button');
      lists.appendChild(button2s);

      var t2s = document.createTextNode("DEL");
      button2s.appendChild(t2s);

      button2s.addEventListener("click", remove_div);

    }
    
    function add_div3(){
      var div3 = document.createElement('ul');
      div1.appendChild(div3);

      var listss = document.createElement('li');
      div3.appendChild(listss);
      div3.className = 'inner-sub-div';

      div3.id = 'sub_test-' + document.querySelectorAll('.inner-sub-div > .msg3').length;

      listss.className = 'msg3';
      div3.appendChild(listss);

      var inputss = document.createElement('input');
      listss.appendChild(inputss);
      inputss.placeholder="sub child";

      var button1ss = document.createElement('button');
      listss.appendChild(button1ss);

      var t1ss = document.createTextNode("ADD");
      button1ss.appendChild(t1ss);

      var button2ss = document.createElement('button');
      listss.appendChild(button2ss);

      var t2ss = document.createTextNode("DEL");
      button2ss.appendChild(t2ss);

      button2ss.addEventListener("click", remove_div);

    }

    function remove_div(){
      var check = document.getElementById('test-0');
      check.parentNode.removeChild(check);
    }

  
}
.ui-modal{
    width: 200px;
    border: 1px solid red;
    position: relative;
    left:0;
    z-index: 55;
}
.sub-div{
    margin-top: 10px;
    width: 200px;
    height: 50px;
    left: 100px;
    border: 1px solid blue;
    position: relative;
    z-index: 66;
}
.inner-sub-div{
    margin-top: 10px;
    width: 200px;
    left: 250px;
    border: 1px solid blue;
    position: relative;
    z-index: 77;

}
.plus{
    border: 1px solid red;
    display: inline-block;
}
<div class="wrapper">
<input type="button" value="ADD" onclick="add_div();">
</div>

The buttons are dynamically generated using append child method with an added event listener for the add button, which appends an input field with add and delete buttons upon clicking. While clicking the add button successfully adds nodes, I am facing difficulties in retrieving the ID on clicking the delete button.

I have manually deleted a parent node with the ID test-0.

function remove_div(){
      var check = document.getElementById('test-0');
      check.parentNode.removeChild(check);
    }

However, I am looking for a dynamic solution to delete nodes. How can I retrieve the specific ID of the parent node for deletion?

All of these actions need to be performed dynamically as I have manually assigned names to each field.

Answer №1

If you're struggling to find the right ID, consider utilizing the this keyword within your remove_div() function:

For more information on this, you can refer to the documentation here.

Check out this working snippet:

function add_div() {
  var div1 = document.createElement('ul');
  document.body.appendChild(div1);
  div1.className = 'ui-modal';
  div1.id = 'test-' + document.querySelectorAll('.ui-modal > .msg1').length;
  var check = div1.id;

  var list = document.createElement('li');

  list.className = 'msg1';
  div1.appendChild(list);

  var input = document.createElement('input');
  list.appendChild(input);
  input.placeholder = "parent";

  var button1 = document.createElement('button');
  list.appendChild(button1);

  var t1 = document.createTextNode("ADD");
  button1.appendChild(t1);
  button1.addEventListener("click", add_div2);

  var button2 = document.createElement('button');
  list.appendChild(button2);

  var t2 = document.createTextNode("DEL");
  button2.appendChild(t2);

  button2.addEventListener("click", remove_div);
  

  function add_div2() {
    var div2 = document.createElement('ul');
    div1.appendChild(div2);

    var lists = document.createElement('li');
    div2.appendChild(lists);
    div2.className = 'sub-div';

    div2.id = 'sub_test-' + document.querySelectorAll('.sub-div > .msg2').length;

    lists.className = 'msg2';
    div2.appendChild(lists);

    var inputs = document.createElement('input');
    lists.appendChild(inputs);
    inputs.placeholder = "child";

    var button1s = document.createElement('button');
    lists.appendChild(button1s);

    var t1s = document.createTextNode("ADD");
    button1s.appendChild(t1s);

    button1s.addEventListener("click", add_div3);


    var button2s = document.createElement('button');
    lists.appendChild(button2s);

    var t2s = document.createTextNode("DEL");
    button2s.appendChild(t2s);

    button2s.addEventListener("click", remove_div);

  }

  function add_div3() {
    var div3 = document.createElement('ul');
    div1.appendChild(div3);

    var listss = document.createElement('li');
    div3.appendChild(listss);
    div3.className = 'inner-sub-div';

    div3.id = 'sub_test-' + document.querySelectorAll('.inner-sub-div > .msg3').length;

    listss.className = 'msg3';
    div3.appendChild(listss);

    var inputss = document.createElement('input');
    listss.appendChild(inputss);
    inputss.placeholder = "sub child";

    var button1ss = document.createElement('button');
    listss.appendChild(button1ss);

    var t1ss = document.createTextNode("ADD");
    button1ss.appendChild(t1ss);

    var button2ss = document.createElement('button');
    listss.appendChild(button2ss);

    var t2ss = document.createTextNode("DEL");
    button2ss.appendChild(t2ss);

    button2ss.addEventListener("click", remove_div);

  }

  function remove_div() {
    var check = this.closest("ul"); // TAKIT: Suggestion
    check.parentNode.removeChild(check);
  }

}
.ui-modal {
  width: 200px;
  border: 1px solid red;
  position: relative;
  left: 0;
  z-index: 55;
}

.sub-div {
  margin-top: 10px;
  width: 200px;
  height: 50px;
  left: 100px;
  border: 1px solid blue;
  position: relative;
  z-index: 66;
}

.inner-sub-div {
  margin-top: 10px;
  width: 200px;
  left: 250px;
  border: 1px solid blue;
  position: relative;
  z-index: 77;
}

.plus {
  border: 1px solid red;
  display: inline-block;
}
<div class="wrapper">
  <input type="button" value="ADD" onclick="add_div();">
</div>

In any case, I believe there's room for enhancement in your code, as all your add_divx() functions appear to be quite similar.


⋅ ⋅ ⋅

With that in mind, here's a simplified approach to make your code more manageable:

  • Utilize HTML for creating distinct template elements to keep HTML within HTML,
  • Add a class to your template elements and employ display: none; in their CSS,
  • Consolidate all element addition into a single function with parameters.

I've streamlined the CSS and condensed the snippet to make it concise and visually appealing.

Here's the revised version:

function append(level, elm) {
  if (!elm) elm = document.body;
  else elm = elm.closest('ul');
  var appended = document.querySelector('#temp' + level).children[0].cloneNode(true);
  elm.appendChild(appended);
}

function remove_div(button) {
  var elm = button.closest("ul");
  elm.parentNode.removeChild(elm);
}
.templates { display: none; }

ul {
  background: rgba(255, 255, 255, 0.75);
  width: 200px;
  margin: 8px 0;
  padding-top: 4px;
  padding-bottom: 4px;
}

.level1 { border: 2px solid #f88; }
.level2 { border: 2px solid #8f8; }
.level3 { border: 2px solid #88f; }
<div class="wrapper">
  <input type="button" value="ADD" onclick="append(1);">
</div>
<div class="templates" id="temp1">
  <ul class="level1">
    <li>
      <input placeholder="parent">
      <button onclick="append(2, this)">ADD</button>
      <button onclick="remove_div(this)">DEL</button>
    </li>
  </ul>
</div>
<div class="templates" id="temp2">
  <ul class="level2">
    <li>
      <input placeholder="child">
      <button onclick="append(3, this)">ADD</button>
      <button onclick="remove_div(this)">DEL</button>
    </li>
  </ul>
</div>
<div class="templates" id="temp3">
  <ul class="level3">
    <li>
      <input placeholder="sub-child">
      <button onclick="remove_div(this)">DEL</button>
    </li>
  </ul>
</div>

(I must say, I'm quite pleased with the result.)

I hope this makes things easier for you.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

A guide on manipulating an input field to trigger md-datepicker upon clicking

What is the best way to convert an input text into a fire md-datepicker and achieve a similar result like this? ...

Mastering the alignment of Material-UI Menu items

When using the menu and menu item components of material-ui to create a select dropdown menu, I encountered an unusual issue where the dropdown menu always expands to the left side of the box, as shown in the image below: https://i.stack.imgur.com/ykRrp.jp ...

What is the most effective way to create a live preview using AngularJS and CSS?

Is there a way to dynamically change the background color of the body based on the hexadecimal value entered in a textfield, without using jQuery? I want the change to happen live as the user types. The current code works but it doesn't feel right. I ...

Create a dynamic AppBar Toolbar in React Admin that changes based on the current page

Recently delving into the world of React, I've been facing some challenges when it comes to loading IconButtons onto the toolBar of an AppBar (from Material UI). For instance, I'm looking to have two specific IconButtons displayed on pageA and d ...

Ways to prevent other users from clicking or modifying a particular row

I have a data table in my project that will be accessed by multiple users simultaneously. My requirement is that once a row is selected and edited by one user, it should become unclickable for other users who are also viewing the same page or data table. ...

Issue with Framer Motion Modal: Animation presence fails to function

Currently, I am facing an issue with the exit animation of a modal created using framer motion. While the initial animation on opening the modal works perfectly fine, the exit animation fails to trigger and the modal disappears abruptly without any transit ...

Can you tell me the standard font size in Internet Explorer 9?

After examining this particular website, I found the default styling used by IE 9. The body selector in particular appears as follows: body { display: block; margin: 8px; zoom: 1; } I would have expected a font-size declaration in this code, but su ...

inquiry on php function properties

I have a PHP file containing two functions. <?php function first () { //in real case more conditions echo "first"; return true; } function second () { //in real case more conditions echo "second"; return true; } first(); second(); ?> And in an ...

Finding a problem in node.js

I have encountered a problem while creating a server game using node.js. I am seeking assistance to resolve this issue. Here is the specific problem: https://i.stack.imgur.com/FMlsL.png app.js: var express = require('express'); var app = expr ...

Assign a unique value to every line in a JSON string within the Vue.js hierarchy of components

I created a Vue component that initializes an empty list and an object like this: data: function(){ return { list: [], newThing: { body: '', }, }; }, The list is then populated with JSON data fetched ...

A SyntaxError was caught due to an unexpected token '<' in the constants.js file when using react and vite

I'm trying to display a button in the sidebar with a name and an icon. I've been iterating through the list of categories, which are imported from the 'constants.js' file located in the utils folder. However, instead of getting the desi ...

Problem with IE off-canvas scrolling

Currently, I am facing an issue with the scrolling functionality of an off-canvas sidebar on my Joomla 3 website. It seems to be working fine in Chrome and Firefox, but when it comes to Internet Explorer, the visible scroll bar refuses to move when attempt ...

Please provide me with the coordinates (latitude and longitude) for that address

I am looking to integrate the Google geocoder into my website. I want to be able to input any location address and receive the latitude and longitude coordinates for that location. Are there any helpful tutorials available? For reference, I found a simila ...

Why is it that my terminal doesn't close after my gulp process completes?

I am looking to implement React in my NodeJs application. Here is the content of my gulpfile: let gulp = require('gulp'); let uglify = require('gulp-uglify'); let browserify = require('browserify'); let babelify = require(& ...

Attempting to utilize the LLL algorithm as described on Wikipedia has led to encountering significant challenges

I'm struggling with determining whether my issue stems from programming or understanding the LLL algorithm mentioned on Wikipedia. To gain a better understanding of the LLL algorithm, I attempted to implement it following the instructions outlined on ...

Navigation structure on a website built with HTML

As I dive into HTML5 programming, I am working on creating a simple navigation menu with links to different HTML pages such as "1.html", "2.html," and others. However, when I click on a link like "1.html," it takes me to a new page where the navigation men ...

Mastering Meteor: Techniques for Manipulating Mongodb Data in Real Time Display

Within my Meteor application, I have accomplished the successful publication of data from the server and its subscription on the client side. Instead of directly displaying raw data on the client's screen, I am interested in performing some calculatio ...

JavaScript Event Listener not Working Properly

I've been attempting to implement a feature on my website where the header hides when scrolling down and re-appears when scrolling up. However, I'm struggling to make use of the code snippet below to achieve this functionality. Despite my thoroug ...

Include a floating element within a modal box

I am trying to display some cards within a Bootstrap modal form. Inside the modal, I want the cards to appear in two columns by using the "col-md-5" class. .mycard.col-md-5 card contents However, when I use the "col-md-5" class, it adds a property o ...

Utilizing JQuery for adjusting the CSS top property

I needed to overlay text on an image, so I used CSS for this purpose. However, as I incorporated Bootstrap and hesitated to include absolute positioning in the CSS file, I faced issues with centering the text when resizing the image. To tackle this problem ...