Optiq
Optiq

Reputation: 3182

How can I empty cloned inputs with JQuery?

I concocted a script to clone and rename input fields in my questionnaire. When I tested it out I seen that it also clones the information typed into the fields.

I tried using .val('') and .reset() but neither of them worked. After doing a little research I learned that it was because I have a combination of input fields and they don't exactly work for all of them. So I decided to create an "if" statement to dig in a little deeper, which still doesn't clear the cloned inputs. I checked the console and didn't get any errors, so I have no clue what's going wrong.

here's the code

$("#p20_01_yes").click(function(){
var num = $('.clone_el').length,
newNum = new Number(num + 1),
clonedFieldset = $("#cloner").clone().prependTo("#page20");

clonedFieldset.attr('id',('cloner')+newNum).find("input, textarea, select, label, #cus_title").each(function() {
    var item = $(this),
    type = this.type,
    tag = this.tagName.toLowerCase();

    item.attr('name', item.attr('name') +newNum).attr('id', item.attr('id') +newNum);
    $('#cus_title').text("Customer "+newNum);

    if (type =='text'||tag=='textarea')
    this.value='';

    else if (tag=='select')
    this.selectedIndex=0;

});
});

The section I'm cloning has text inputs, textareas and select inputs. I'd post the HTML as well but it's over the 30,000 character limit of these posts. If you would like a JSFiddle I can throw one together but seeing as to how I'm still pretty new to JQuery and Javascript I figured it might just be my syntax.

Here's the JSfiddle: https://jsfiddle.net/Optiq/ct2ju1cb/

Upvotes: 0

Views: 1126

Answers (3)

Optiq
Optiq

Reputation: 3182

I modified my coding to this

$("#add_cus").click(function(){
    var num = $('.clone_el').length;
    var newNum = new Number(num+1);
    var newClone = $("#cloner").clone().appendTo("#clone_wrap");

    newClone.attr('id',('cloner')+newNum).find("input, textarea, select, #cus_title").each(function(){

        var item = $(this);
        var type = this.type;
        var tag = this.tagName.toLowerCase();

        if(type=='text'||tag=='textarea'){
            item.attr('name', item.attr('name')+newNum).attr('id', item.attr('id')+newNum).val('');
        }
            else if(tag=='select'){
            item.attr('name', item.attr('name')+newNum).attr('id', item.attr('id')+newNum).selectedIndex=0;
            }
            else if(item.attr('id')=='cus_title'){
            item.text("Customer "+newNum);  
            }
        });
    });

I know you guys said the way I was going about it wasn't the best way to do it, but this clones all the inputs I need cloned and it effects the names and IDs according to how I have my form set up. I appreciate everyone's input and want to look more into the other answers given because they do look extremely useful.

My issue with them is while I see how they work, I don't exactly understand how I can apply my divs and their styles to the format plus they look extremely tedious. Cloning the fieldset automatically clones everything and all I have to do from there is just focus the code on the inputs.

If anyone sees any problems with this please let me know. As of right now it clones everything properly and my PHP script works well with it without any errors so I'm happy with the way it works. Thanks again for all the input as I have started studying angular js and json a bit more and can see the value in applying it. I just can't afford the time right now for re-building everything all over again.

Upvotes: 0

Frondor
Frondor

Reputation: 3466

It's really hard to do what you want in the way you've created your code. I decided to make a new script, simplifying the logic for you. It isn't the best practice anyway, but in my opinion its way better than your actual code :D I hope you can understand it, and be able to adjust is as much as you want. You'll have to build the config object by your needs, that's most likely all you have to do.

Basically, the main idea of this script is to build the form "on the go", by setting un a config object (JSON array), and then iterating over it to build and render the inputs.

Note Just for simplicity sake I'm using bootstrap to add a nicer look to the form, you should adapt it to your template, or include bootstrap on it too (why not? :D)

HTML

<div id="content" class="container">
    <button id="addcustomer" class="btn btn-sm btn-success pull-right">Add customer</button>
    <div id="page">
        <form action="/form.php" id="form">
            <!-- form content goes here -->
        </form>
    </div>
</div>

jQuery:

$(document).ready(function () {
    // first, set a JSON object with this format to config the questions/inputs, actually it supports text and number inputs, select and textarea
    var config = [
        {"type": "text", "name": "name", "label": "Name"},
        {"type": "select", "name": "gender", "label": "Gender", "options": [
            {"value": "m", "text": "Male"},
            {"value": "f", "text": "Female"}
        ]},
        {"type": "number", "name": "age", "label": "Age"},
        {"type": "textarea", "name": "bio", "label": "Bio"}
    ];

    var customer = 1; // start the counter for customers
    $('#addcustomer').on('click', function () {
        customer++; //when the button is clicked, increase customer counter and trigger the function to create the new inputs
        addNewCustomer(customer);
    });    

    //this function pass the customer's count to buildForm() function to build the input names and ids
    function addNewCustomer(cn) {
        buildForm(cn);
    }

    //the buildForm() function creates the HTML with the inputs coming from buildInput() function.
    function buildForm(cn) { // cn =customer number
        var formHtml = $('#form');
        formHtml.append('<h2 class="page-header"><i class="glyphicon glyphicon-user"></i> Customer ' + cn + '</h2>');
        $.each(config, function (index, item) {
            var entry = '<div class="form-group panel panel-default panel-body">' + buildInput(item, cn) + '</div>';
            formHtml.append(entry);
        });
    }

    // The buildInput() function is called on each iteration over the config object made on buildForm(), it is in charge of building the labels and input for each question, one by one.
    function buildInput(item, cn) {
        var label = '<label for="' + item.name + cn + '">' + item.label + '</label>';
        var input;
        if (item.type === "text") {
            input = '<input type="text" name="' + item.name + cn + '" id="' + item.name + cn + '" class="form-control"/>';
            return label + input;
        } else if (item.type === "select") {
            var options;
            $.each(item.options, function (i, op) {
                options += '<option value="' + op.value + '">' + op.text + '</option>';
            });
            input = '<select name="' + item.name + cn + '" id="' + item.name + cn + '" class="form-control">' + options + '</select>';
            return label + input;
        } else if (item.type === 'number') {
            input = '<input type="number" name="' + item.name + cn + '" id="' + item.name + cn + '" class="form-control"/>';
            return label + input;
        } else if (item.type === 'textarea') {
            input = '<textarea name="' + item.name + cn + '" id="' + item.name + cn + '" class="form-control"/>';
            return label + input;
        } else {
            return 'Couldn\'t create this input, probably there is no conditional for its type';
        }
    }

    // finally, you build the first form that is shown by default, let's say "Customer 1 form"
    buildForm(customer);
});

DEMO

on this fiddle: http://jsfiddle.net/tofs46o8/

The code is self explanatory as you can see on the comments, please read them.

Upvotes: 1

Dan O
Dan O

Reputation: 6090

You have a few problems with your script:

TL;DR

The new elements you're creating are being emptied, you're just adding them to the top of the page (see #1 above) and you're somehow changing the wrong customer title element (#3) so it just looks like the new elements aren't being emptied. Fixing those problems is a good place to start, but doing so might uncover additional problems (#2, #4).

Details ( not a complete list of everything that is wrong )

  • you're prepending the new items instead of appending them, so they're getting added to the top of the page instead of the bottom
  • you're not correctly deriving the name and id attrs of your new elements. item.attr('name') +newNum resolves to NaN, which you can see by inspecting the new elements in your browser's developer console. You then have a whole lot of elements with id="NaN" which is definitely not what you want
  • you're cloning #cusTitle but not changing its id, which means the return value of $("#cusTitle") will be undefined. in my browser, it turns out that the return value is the second #cusTitle, which is not what I'd expect, and it's not what you want here anyway
  • you're giving new name attrs to some items which didn't have them originally (like all of the <label> elements I checked)

Upvotes: 1

Related Questions