Removing a Div with Dynamic Parameters

I'm struggling to implement a feature in my form that allows the user to add multiple entries, but I'm having trouble with the removal aspect.

Here is the JavaScript code:


        var i = 1;
        var divContent = document.getElementById('formulario');

        //Click to add a field
        function cria() {
            //This adds HTML Inputs and divs with IDs based on the 'i' variable which increments
            document.getElementById('formulario').innerHTML += '<div class="mb-1 col-3" id="div'+i+'"><label for="nomeTx0" class="form-label">Nome</label><input type="text" class="form-control" id="nomeTx'+i+'" name="nomeTx'+i+'" required></div><div class="mb-1 col-3" id="div2'+i+'"><label for="taxa'+i+'" class="form-label">Valor</label><input type="float" class="form-control" id="taxa'+i+'" name="taxa'+i+'" required></div><a href="#" data-id="1" onclick="remove(div'+i+',div2'+i+')" id="adicionarCampo">- Remover campo</a>';
            i++;
        }

        function remove(div1, div2){
            var div = document.getElementById(div1);
            var div2 = document.getElementById(div2);
            div.remove();
            div2.remove();
            i--;
        }
    

And here is the corresponding HTML code:


        <form>
            <h4 class="card-tittle text-center">Taxas</h4>
            <div id="formulario" class="form row align-items-start">
                <div class="mb-1 col-3" id="0">
                    <label for="nomeTx0" class="form-label">Nome</label>
                    <input type="text" class="form-control" id="nomeTx0" name="nomeTx0" required>
                </div>
                <div class="mb-1 col-3" id="0">
                    <label for="taxa0" class="form-label">Valor</label>
                    <input type="float" class="form-control" id="taxa0" name="taxa0" required>
                </div>
            </div>
            <a href="#" data-id="1" onclick="cria()" id="adicionarCampo">+ adicionar campo</a>
            <div class="mb-1 col-lg-12" style="text-align: center;">
                <button class="btn btn-primary col-5" id="Enviar" type="submit" text="Enviar">Adicionar Taxas</button>
            </div>
        </form>

    

The issue arises when using ID="taxa"+i and calling the remove() function, causing an error stating that the variable is null.

Answer №1

This approach may need some rethinking.

The main issue lies in your reliance on ids to manage the elements you want to manipulate. This could lead to problems as concatenating ids onto dynamically created elements using long strings with variables can make your code fragile and difficult to scale. It's generally advisable to minimize the use of ids as much as possible.

A better alternative would be to utilize the HTML <template> element. By taking a look at the revised code below, you'll notice that all unnecessary ids have been removed, eliminating the need for them altogether. Instead of creating lengthy strings with variable inserts, you simply clone the template whenever necessary. Employing "event delegation" along with a well-structured HTML setup allows you to set up a centralized click event on a parent wrapper element. Whenever a click occurs, you can easily determine the specific element that was clicked (via event.target). If it happens to be a remove button, you can directly eliminate the closest enclosing wrapper ancestor to that particular button.

You can now effortlessly add or remove items without the complexities associated with ids or tracking variables!

// Grab references to the template, outer div, and the add "button"
const template = document.querySelector("template");
const wrapper = document.querySelector(".wrapper");
const add = document.querySelector(".add");

// Implement the add event using Javascript instead of inline HTML
add.addEventListener("click", function(event){
  var clone = template.content.cloneNode(true); // Replicate the template
  wrapper.appendChild(clone);
});

// Set up a wrapper level click event where any clicks within will bubble up
wrapper.addEventListener("click", function(event){
  // Check if the clicked element is the remove "button"
  if(event.target.classList.contains("remove")){
    // Simply remove the nearest ancestor div that contains the group
    // and delete it.
    event.target.closest("div.templateWrapper").remove();
  }
});
.mb-1.col-lg-12 {
  text-align:center;
}

.mb-1.col-3 {
  margin:2px;
}

.add, .remove {
  cursor:pointer;
  color:blue;
}

.labelName { display:inline-block; width:3em; }

/* Enhances visibility of groups */
.templateWrapper, .form {
  background-color:aliceblue;
  padding:5px;
  margin:8px;
}
<!-- Initially hidden from the page view.
     Used whenever necessary for copying. -->
<template>
  <div class="templateWrapper">
    <div class="mb-1 col-3">
      <label class="form-label"><span class="labelName">Name</span>
        <input type="text" class="form-control" name="nameTx" required>
      </label>
    </div>
    <div class="mb-1 col-3">
      <label class="form-label"><span class="labelName">Value</span>
        <!-- No "float" type for input -->
        <input class="form-control" name="rate" required>
      </label>
    </div>
    <span class="remove">- Remove field</span>
  </div>
</template>

<form>
  <h4 class="card-tittle text-center">Rates</h4>
  <span class="add">+ add field</span>  
  <div class="wrapper">
    <div class="form row align-items-start">
      <div class="mb-1 col-3">
        <label class="form-label"><span class="labelName">Name</span>
          <input type="text" class="form-control" name="nameTx0" required>
        </label>
      </div>
      <div class="mb-1 col-3">
        <label class="form-label"><span class="labelName">Value</span>
          <input type="float" class="form-control" name="rate0" required>
        </label>
      </div>
    </div>
  </div>
  <div class="mb-1 col-lg-12">
    <button class="btn btn-primary col-5" type="submit">Add Rates</button>
  </div>
</form>

Answer №2

When trying to call the remove function, ensure you are passing the correct IDs of the HTML elements as parameters.

Consider this revised code:

function remove(id1, id2){
        //Are you passing IDs or something else to this function?
        console.log(id1, id2);  
    
        // Force the arguments passed to be valid ID values for testing purposes

 
        var element1 = document.getElementById('element1'); // ID is element1
        var element2 = document.getElementById('element2'); // ID is element2

        // Instruct the parent node to remove its child  
 
        element1.parentNode.removeChild(element1);   
        element2.parentNode.removeChild(element2);                   
    }

Answer №3

Your code is experiencing an issue because you are passing the entire element instead of a string to the remove function. This causes document.getElementById to not find anything, as it expects a string parameter. I made some improvements to your code and addressed the issue where the link "- Remover campo" was not being deleted when removing fields. By adding a third argument to the remove function, I was able to fix this issue.

    var i = 1;
var divContent = document.getElementById('formulario');

//Click to add a field
function cria() {
    //This adds HTML inputs and divs with IDs that increment based on 'i'
    document.getElementById('formulario').innerHTML += '<div class="mb-1 col-3" id="div'+i+'"><label for="nomeTx0" class="form-label">Nome</label><input type="text" class="form-control" id="nomeTx'+i+'" name="nomeTx'+i+'" required></div><div class="mb-1 col-3" id="div2'+i+'"><label for="taxa'+i+'" class="form-label">Valor</label><input type="float" class="form-control" id="taxa'+i+'" name="taxa'+i+'" required></div><a href="#" data-id="1" onclick="remove(`div'+i+'`, `div2'+i+'`, `div'+i+'remove`)" id="div'+i+'remove">- Remover campo</a>';
    i++;
}
function remove(div1, div2, link){
    var div = document.getElementById(div1);
    var div2 = document.getElementById(div2);
    var link = document.getElementById(link);
    divContent.removeChild(div);
    divContent.removeChild(div2);
    divContent.removeChild(link)
    i--;
}

Answer №4

If you want to get your code working, the simplest way is to modify your function "cria". (although it may not be the optimal solution)

You forgot the single quotes.

onclick="remove(div'+i+',div2'+i+')"

You should use this format instead.

onclick="remove(\'div'+i+'\',\'div2'+i+'\')"

Javascript doesn't recognize these parameters as strings by default.

Here is the updated version of the "cria" function after making the necessary changes.

function cria() {
    //This function adds HTML Inputs and divs with IDs that increment based on the variable 'i'
    document.getElementById('formulario').innerHTML += '<div class="mb-1 col-3" id="div'+i+'"><label for="nomeTx0" class="form-label">Nome</label><input type="text" class="form-control" id="nomeTx'+i+'" name="nomeTx'+i+'" required></div><div class="mb-1 col-3" id="div2'+i+'"><label for="taxa'+i+'" class="form-label">Valor</label><input type="float" class="form-control" id="taxa'+i+'" name="taxa'+i+'" required></div><a href="#" data-id="1" onclick="remove(\'div'+i+'\',\'div2'+i+'\')" id="adicionarCampo">- Remover campo</a>';
    i++;
}

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

Improve navigation by integrating jQuery validation to resolve input errors seamlessly

I have been working with the jQuery validation plugin and Bootstrap. I recently added a fixed navigation bar at the top of the page using Bootstrap CSS. However, I encountered an issue where the fixed navigation was overlapping with the error message for i ...

Retrieve information from a pair of models

Hey there, I need some help. Can someone please guide me on how to obtain the 'topics' array and append it to res.view()? I've tried multiple approaches but keep getting 'undefined' in the 'topics' array. Subjects.qu ...

Ways to style a div element in CSS to achieve a unique shape

Hello there! I'm looking to achieve a tilted background div effect. Anyone have any tips or ideas on how I can do this? I'm new to web development and would appreciate the guidance. https://i.stack.imgur.com/wyj1X.png ...

The React JSX error you encountered is due to the missing return value at the end of the arrow function

After implementing my code, I noticed the following: books.map(({ subjects, formats, title, authors, bookshelves }, index) => { subjects = subjects.join().toLowerCase(); author = authors.map(({ name }) => name).join() ...

Steps for implementing drag-and-drop feature for a div in a template

I am looking to implement draggable functionality on a div element dynamically. The unique id for the div is generated using the code snippet below: var Exp=0; view.renderFunction = function(id1){ var id= id1 + Exp++; $("#"+id).draggable(); }; In my ...

Verify the front-end application and authenticate the backend REST API

My project involves developing a REST API and application logic on the client-side, keeping them separate and independent of each other. Now I am looking to implement an authentication system that will automatically authenticate users both on the client-si ...

What is the best way to engage in conversations with several users using socket.io?

Currently, I am in the process of developing a chat application with authentication. The implementation involves socketio for real-time communication and jwt along with cookies for user authentication. The connection to the database has been successfully e ...

How do you display a nested object in React after merging it?

To display the JSON below as an image, click https://i.stack.imgur.com/tixu4.png let finalSplit = [ { start: "73", end: "76", splits: [ { word: "Now", start: "73", ...

Is there a way to remove or replace the existing polyline to ensure that only one is displayed at a time?

My goal is to have a single line drawn from the closest marker to a static position. I can determine which marker is the closest by sorting the distances, but if a new marker is added and is closer than the previous closest one, a new polyline is drawn wit ...

What could be causing the computed property in Vue 2 component to not return the expected state?

I'm encountering an issue with my Vue component where it fails to load due to one of its computed properties being undefined: Error: Cannot read properties of undefined (reading 'map') Here is the snippet of the computed property causing ...

Retrieve the information transmitted to an EJS file within a separately included JavaScript file

I'm currently utilizing express js to render a file by using: res.render('plain',{state:'admin'}) The file plain.ejs includes main.js: <script src ="/main.js"></script> I need assistance on how to access the state v ...

JavaScript - Navigating through JSON object in reverse (from leaf to root) direction

FamilyTree= { "name":"Family", "photo":"images/family.jpg", "members":[ { "name":"Parent", "photo":"images/parent.jpg", "relationships":[ { "name":"Spouse", "photo":"images/spouse.jpg" }, ...

What is the appropriate time to end a connection in MongoDB?

Utilizing Node.js Express and MongoDB for my API, I encountered an issue with the mongoClient connection. The data fetching process worked smoothly at first, but without refreshing it threw an error stating "Topology is closed." const express=require("e ...

React-select: issue with maintaining selected option on input

Hello everyone, I am new to React and seeking some assistance in reviewing my code. I have a component called Bucket that contains multiple challenges as separate components. Here is a simplified version of the code: class CLL_Bucket extends Component { ...

Dropping challenging shapes in a block-matching game similar to Tetris

I'm currently working on a game similar to Tetris, but with a twist. Instead of removing just one line when it's full, I want to remove all connected pieces at once. However, I've run into a roadblock when trying to implement the hard-drop f ...

Encountering issues with connecting to the MongoDB server through Node.js

When working with MongoDB in Python, everything runs smoothly without any errors. However, when using Node.js, an error keeps popping up. Can someone please guide me on how to resolve this issue? jdcaovuwqxoqppwwqmjcawpwuaciwowjqwqhpaiwdoqi Below is the ...

Pass information from an array of objects to a visual component

My objective is to display 3 instances of the SearchItem component from locations[0].results[0] and 3 instances from locations[0].results[1] I have an array containing objects with data that I want to display in my SearchItem component: const locations = ...

Using Blob to save CSV file on Safari

Here are the codes I am using to generate a download link for users to download a .csv file from my website. var link = document.createElement("a"); link.id = "csvDwnLink"; window.URL = window.URL || window.webkitURL; var csv = "\ufeff" + CSV, b ...

canvasJS: unable to load the chart

This is my first time using canvajs, but unfortunately, it's not working as expected. Can someone please review my code? data.php <?php header('Content-Type: application/json'); include './traitement.php'; $data =array(); ...

Is there a way to automatically change the value of one input box to its negative counterpart when either of the two input boxes have been filled in?

Consider two input boxes: box1 box2 If a user enters a number in one of the input boxes, we want the value of the other input box to automatically change to the opposite sign of that number. For example: User enters 3 in box1. The value of box2 shoul ...