skip to Main Content

I have a HTML form where a user should be able to add a new label and input field and an associated delete button on the click of an add/plus button.

This is only showing the input field and the delete button at the moment but won’t show a label. I’m trying to make this work for just one input field for now and then I will need to auto increment id to give each new input field a new id and have that also associated with a new label.

I’m slightly confused on how to approach this. I need the user to specify the text that will go in the label. To achieve this, do I need to create it as an input field initially and give them a hint that it’s the label and the other box the input field for the value? Is that a correct understanding of what I should be doing?

Here is my JS code:

function addField() {
    const container = document.getElementById('new-fields');

    // Create new label
    const label = document.createElement('label');
    label.type = 'text';
    label.name = 'label1';
    label.id = 'label1';
    label.for = "input1";

    // Create new input field
    const input = document.createElement('input');
    input.type = 'text';
    input.name = 'new_field[]'; // use brackets to create array in form submission
    input.id = 'input1';

    const deleteBtn = document.createElement('button');
    deleteBtn.type = 'button';
    deleteBtn.textContent = 'Delete';

    deleteBtn.addEventListener('click', () => {
        container.removeChild(input);
        container.removeChild(deleteBtn);
    });

    // Add new input field and delete button to container
    container.appendChild(label);
    container.appendChild(input);
    container.appendChild(deleteBtn);

    // Not sure if I also need to append the container to the document? It works w/out
    document.appendChild(container);

}

3

Answers


  1. You do not need to use document.appendChild(container); because this will throw exception as document can only have 1 child node i.e. <html>

    With your code, label is getting appended to the DOM but you don’t see it because it is empty.
    To see the label, you should add some text to it.
    Try
    label.innerHTML = 'Label Name'

    Working fiddle: https://jsfiddle.net/u2z3q6vw/

    Login or Signup to reply.
  2. The label is not a part of the form input (source). So to display the label text, just use .innerText like this:

    function addField() {
        const container = document.createElement('div');
    
        // Create new label
        const label = document.createElement('label');
        label.innerText = 'text';
        label.name = 'label1';
        label.id = 'label1';
        label.for = "input1";
    
        // Create new input field
        const input = document.createElement('input');
        input.type = 'text';
        input.name = 'new_field[]'; // use brackets to create array in form submission
        input.id = 'input1';
    
        const deleteBtn = document.createElement('button');
        deleteBtn.type = 'button';
        deleteBtn.textContent = 'Delete';
    
        deleteBtn.addEventListener('click', () => {
            container.removeChild(input);
            container.removeChild(deleteBtn);
        });
    
        // Add new input field and delete button to container
        container.appendChild(label);
        container.appendChild(input);
        container.appendChild(deleteBtn);
    
        // Not sure if I also need to append the container to the document? It works w/out
        
        document.body.appendChild(container);
    
    }
    
    addField();

    Instead of using

    ...
    const container = document.getElementById('new-fields');
    ...
    document.appendChild(container)
    

    just using

    ...
    const container = document.createElement('div');
    ...
    document.body.appendChild(container)
    

    for better way.

    Login or Signup to reply.
  3. Just creating a small web component that comes with a label and a delete button solves all of the problems you’re facing.

    customElements.define('labeled-input', class LabeledInput extends HTMLElement {
      #label = Object.assign(document.createElement('label'), { htmlFor: 'input' });
      #input = Object.assign(document.createElement('input'), { id: 'input' });
      #button = Object.assign(document.createElement('button'), { textContent: '🗑', type: 'button' });
    
      constructor() {
        super().attachShadow({ mode: 'open' }).append(this.#label, this.#input, this.#button);
        this.#button.addEventListener('click', () => this.remove());
      }
      
      set label(txt) { this.#label.textContent = txt; }
      get label() { return this.#label.textContent; }
      
      set value(val) { this.#input.value = val; }
      get value() { return this.#input.value; }
      
      static get observedAttributes() { return ['label', 'value'] }
      attributeChangedCallback(attr, oldVal, newVal) {
        if (oldVal === newVal) return;
        this[attr] = newVal ?? '';
      }
    });
    <button type="button" onclick="document.getElementById('new-fields').append(Object.assign(document.createElement('labeled-input'), { label: 'Shiny Label', value: 'Initial value' }))">+</button>
    <div id="new-fields"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search