0

I have a jquery code that clones a "selector" wherein it is a parent of many other elements.

EDIT : I added the function that calls the "cloneMore". It supposed to be called when the user clicks the button inside the row and creates another row below it.

EDIT 2 : I added the table that the <tr> belongs to. I tried to run it without the <tr> <td> tags and the function works! But sadly it removes it from the html table. Why does this happen?

jquery snippet

$(document).on('click', '.add-form-row', function(e){
        alert("Button Click!");
        e.preventDefault();
        cloneMore('.form-row.spacer:last', 'form');
        return false;

function cloneMore(selector, prefix) {
        var newElement = $(selector).clone(true);

        newElement.find('input[type=text]').each(function() { //loops through the textfields
            console.log("print1");
        });
        
        newElement.each(function () {
            console.log("print2");
        });

html code

    <div class="display_table">
    <table class="table table-hover table-striped">
        <thead class="thead-dark">
            <tr class="tablerow">
                <th scope="col">Item</th>
                <th scope="col">Item Description</th>
                <th scope="col">Quantity</th>
                <th scope="col">Delete</th>
            </tr>
        </thead>
        <tbody>
            {{ formset.management_form }}
            {% for form in formset %}
            <div class="row form-row spacer">
                <tr scope="row">
                    <div class="input-group">
                        <td><input type="text" name="form-0-item" class="form-control" id="id_form-0-item" value="" readonly="readonly"></td>
                        <td><input type="text" name="form-0-description" class="form-control" id="id_form-0-description" value="" readonly="readonly"></td>
                        <td><input type="text" name="form-0-quantity" class="form-control" id="id_form-0-quantity" value="" readonly="readonly"></td>
                        <div class="input-group-append"><td><button class="btn btn-success add-form-row">+</button></td></div>
                    </div>
                </tr>
            </div>
            {% endfor %}
        </tbody>
    </table>
</div>

However, it doesn't even pass through the loop even once and I don't get a "print" in the console. I'm sure that there is a text field inside the parent. In this case its the div with class "row form-row spacer"

Is there something wrong with my syntax? I've seen somewhere where they get the parent through a selector but in my case I put it in a variable. Is there anything wrong or any work around this?

Czar Luc
  • 85
  • 1
  • 2
  • 11
  • how are you calling the function, if you do cloneMore('.input-group') or cloneMore('.form-row.spacer') it will iterate through the inputs inside of that html-element. – Bjarke Handsdal Jun 26 '20 at 08:47
  • Please add a snippet (edit and click `[<>]`), see [mcve]. Your question mentions "inside parent loop" but there's only one loop. Your code shows `cloneMore` but it doesn't seem to be called. Here's a fiddle (but you should provide a snippet in the question) that shows **your code works** fine *as presented*: https://jsfiddle.net/tqLywmh9/ – freedomn-m Jun 26 '20 at 08:49
  • "*In this case its the div with class "row form-row spacer*" - this leads me to suspect you're calling `cloneMore(".row .form-row .spacer")` instead of `cloneMore(".row.form-row.spacer")` https://jsfiddle.net/tqLywmh9/1/ – freedomn-m Jun 26 '20 at 08:53
  • aahh sorry I forgot to include the function that calls it!! – Czar Luc Jun 26 '20 at 09:07
  • I tried to run it and added `cloneMore('.form-row.spacer:last', 'form');` and had a separate each() loop `newElement.each(function () { console.log(this); });` and it goes through it only once and prints `
    ` without the elements inside. Which I expected it to print it 4 times since it has 4 elements inside. Whats wrong?
    – Czar Luc Jun 26 '20 at 09:46

1 Answers1

0

I think I kind of figured it out. I was trying to select the <input> tags even without referencing the <td> and <tr> tags. So jquery didn't know what I was trying to select. So after I made some changes in the whole table and the jquery script, it works just as I intended it would. However, any suggestions on how I could improve this code will be appreciated! I'm putting this up in case someone needs it.

Also, I forgot to credit to this Stack Overflow answer for the snippets.

html code

<table class="table table-hover table-striped" id="part_table">
        <thead class="thead-dark">
            <tr class="tablehead">
                <th scope="col">Item</th>
                <th scope="col">Item Description</th>
                <th scope="col">Quantity</th>
                <th scope="col">Delete</th>
            </tr>
        </thead>
        <tbody>
            {{ formset.management_form }}
            {% for form in formset %}
            <div class="row form-row">
                <tr class="tablerow">
                    <td><input type="text" name="form-0-item" class="form-control" id="id_form-0-item" value="" readonly="readonly"></td>
                    <td><input type="text" name="form-0-description" class="form-control" id="id_form-0-description" value="" readonly="readonly"></td>
                    <td><input type="text" name="form-0-quantity" class="form-control" id="id_form-0-quantity" value="" readonly="readonly"></td>
                    <td><button class="btn btn-success add-form-row">+</button></td>
                </tr>
            </div>
            {% endfor %}
        </tbody>
    </table>

jquery snippet

<script type="text/javascript">
    function cloneMore(prefix) { 
        var lastrowtbl = $('#part_table tr.tablerow:last').clone(true); 

        var total = $('#id_' + prefix + '-TOTAL_FORMS').val();
        var currentnum = total - 1

        lastrowtbl.find('input[type=text]').each(function (i, el) {
            console.log(this);
            var name = $(this).attr('name');
            if(name) {
                name = name.replace('-' + currentnum + '-', '-' + total + '-');
                var id = 'id_' + name;
                $(this).attr({'name' : name, 'id' : id}).val('').removeAttr('checked');
            }
        });

        total++;
        $('#id_' + prefix + '_TOTAL_FORMS').val(total);
        $('#part_table tr.tablerow:last').after(lastrowtbl);

        var conditionRow = $('#part_table tr.tablerow:not(:last)');
        conditionRow.find('.btn.add-form-row')
        .removeClass('btn-success').addClass('btn-danger')
        .removeClass('add-form-row').addClass('remove-form-row')
        .html('-');
        return false;
    }

    $(document).on('click', '.add-form-row', function(e){
        alert("Button Click!");
        e.preventDefault();
        cloneMore('form');
        return false;
    });
    
</script>
Czar Luc
  • 85
  • 1
  • 2
  • 11