Search code examples
javascriptinputdynamically-generated

How to insert and get the value of a dynamically created input field using javascript?


I am creating inputs dynamically depending on a radio button that's clicked and I am having trouble getting the value that is inserted in the input field. I need to print the value that is inserted in a label field that is also created dynamically. It looks like this: https://codepen.io/christmastrex/pen/jOmxmQY

So, if it's selected number 4, 4 input fields are created, and in column 3 I need to print the values inserted in the input fields.

Here is the code:

<div class="row">
    <div class="column">
        <h2>Column 1</h2>

        <div>
            <input type="radio" value="1" name="col1"><label for="1">1</label>
            <input type="radio" value="2" name="col1"><label for="2">2</label>
            <input type="radio" value="3" name="col1"><label for="3">3</label>
            <input type="radio" value="4" name="col1"><label for="4">4</label>
            <input type="radio" value="5" name="col1"><label for="5">5</label>
        </div>

        <button type="button">Add</button>
    </div>

    <div class="column" style="background-color:#ccc;">
        <h2>Column 2</h2>
        <div class="add-input"></div>
    </div>

    <div class="column">
        <h2>Column 3</h2>
        <div class="add-label"></div>
    </div>
</div>
.column {
    float: left;
    width: 30%;
    padding: 10px;
}

.row:after {
    content: "";
    display: table;
    clear: both;
}

#col2 {
    display: none;
}
var inputDiv = document.getElementsByClassName("add-input")[0];
var inputLabel = document.getElementsByClassName("add-label")[0];
var btn = document.querySelector('button[type="button"]');

btn.onclick = function () {
    var radioCheckedNum = document.querySelector('input[type="radio"]:checked')
    .value;

    for (let i = 0; i < radioCheckedNum; i++) {
        var inputFieldValue;
        inputDiv.innerHTML += `<input type="text" id="" value="" name="col2" onChange="${inputFieldValue}"><br><br>`;
        inputFieldValue = document.querySelector('input[name="col2"]').value;
        
        console.log(inputFieldValue);
        
        inputLabel.innerHTML += `<label>Label ${radioCheckedNum} - ${inputFieldValue}</label><br><br>`;
    }
};

Solution

  • Please check the following commented code:

    // GET ELEMENTS MORE EFFICIENTLY BY USING IDs.
    const inputs = document.getElementById('add-input');
    const labels = document.getElementById('add-label');
    const button = document.getElementById('button');
    
    const radios = document.querySelectorAll('input[type="radio"]');
    
    // CREATE UTILITY FUNCTION TO CLEAR ALL CHILDREN FROM A NODE.
    const clear = (node) => {
        while (node.firstChild) {
            node.removeChild(node.lastChild);
        }
    };
    
    const onClickHandler = () => {
        // CLEAR PREVIOUS ELEMENTS (REMOVE IF NOT NEEDED).
        clear(inputs);
        clear(labels);
    
        // GET CHECKED RADIO IN A MORE EFFICIENT WAY (WITHOUT QUERYING THE DOM AGAIN).
        const radio = Array.from(radios).find((input) => input.checked);
    
        // DO NOTHING IF NO RADIO IS CHECKED.
        if (!radio) {
            return;
        }
    
        // GET NUMBER OF INPUTS.
        const number = parseInt(radio.value);
    
        for (let i = 0; i < number; i++) {
            const index = i;
    
            /*
                NEVER USE 'innerHTML' BECAUSE IT IS NOT SAFE!
                INSTEAD, CREATE ELEMENTS PROGRAMMATICALLY USING DOM APIs AS FOLLOWS
             */
            const input = document.createElement('INPUT');
            const label = document.createElement('LABEL');
    
            // SET INPUT ATTRIBUTES.
            input.name = `${index}`;
            input.type = 'text';
    
            // ADD EVENT LISTENER TO EACH INPUT.
            input.addEventListener('input', ({target}) => {
                /*
                    THIS CALLBACK WILL BE FIRED FOR EACH INPUT INDEPENDENTLY.
                    HERE YOU CAN LEVERAGE 'label' REFERENCE TO CHANGE THE CORRESPONDING INNER TEXT.
                 */
                label.innerText = `Label ${index} - "${target.value}"`;
            });
    
            // SET LABEL ATTRIBUTES.
            label.innerText = `Label ${index} - ""`;
    
            // ADD CREATED INPUT TO DOM AND SOME 'br' ELEMENTS.
            inputs.append(
                ...[
                    input,
                    document.createElement('BR'),
                    document.createElement('BR')
                ]
            );
    
            // ADD CREATED LABEL TO DOM AND SOME 'br' ELEMENTS.
            labels.append(
                ...[
                    label,
                    document.createElement('BR'),
                    document.createElement('BR')
                ]
            );
        }
    };
    
    // ADD EVENT LISTENER TO BUTTON USING THE NEWEST API (RECOMMENDED).
    button.addEventListener('click', onClickHandler);
    .column {
        float: left;
        width: 30%;
        padding: 10px;
    }
    
    .row:after {
        content: "";
        display: table;
        clear: both;
    }
    <div class="row">
        <div class="column">
            <h2>Column 1</h2>
    
            <div>
                <input type="radio" value="1" name="col1"><label for="1">1</label>
                <input type="radio" value="2" name="col1"><label for="2">2</label>
                <input type="radio" value="3" name="col1"><label for="3">3</label>
                <input type="radio" value="4" name="col1"><label for="4">4</label>
                <input type="radio" value="5" name="col1"><label for="5">5</label>
            </div>
    
            <button id="button">Add</button>
        </div>
    
        <div class="column" style="background-color:#ccc;">
            <h2>Column 2</h2>
            <div id="add-input"></div>
        </div>
    
        <div class="column">
            <h2>Column 3</h2>
            <div id="add-label"></div>
        </div>
    </div>