Giter VIP home page Giter VIP logo

Comments (11)

elo80ka avatar elo80ka commented on July 21, 2024

From [email protected] on April 18, 2011 20:43:11

Just to add after reading some of the issues. I have found that removing the first row (similar to issue: 3) will not fail but no data from the inlineformsets will be added at all.

from django-dynamic-formset.

elo80ka avatar elo80ka commented on July 21, 2024

From [email protected] on April 18, 2011 20:48:11

Just to note that to add to the strangeness there are no validation errors in the form if I do what I mentioned in comment 1.

from django-dynamic-formset.

elo80ka avatar elo80ka commented on July 21, 2024

From stan.madueke on April 18, 2011 22:32:23

What version of Django are you using? Also, if you could put together a small test project (if it's not too much trouble :), it'd help me get to this faster.

Status: Accepted
Owner: stan.madueke

from django-dynamic-formset.

elo80ka avatar elo80ka commented on July 21, 2024

From [email protected] on April 18, 2011 23:16:08

I'm using Django 1.2.1

I will attempt to put a project together. As the issue is in a much larger project.

from django-dynamic-formset.

elo80ka avatar elo80ka commented on July 21, 2024

From [email protected] on April 19, 2011 05:45:34

I have made this quick example. The admin interface is active so you can look at data.
If you add some data some data and remove the first one the data will not add.

I have been unable (though I need to experiment more) to replicate the problem I am having specifically. I only just got this together and I will continue testing.

Attachment: dynFormError.tar.gz

from django-dynamic-formset.

elo80ka avatar elo80ka commented on July 21, 2024

From [email protected] on May 02, 2011 00:40:12

Did you have a look at the example I made?

from django-dynamic-formset.

elo80ka avatar elo80ka commented on July 21, 2024

From stan.madueke on May 03, 2011 17:01:26

I set up the example (on Django 1.3), but I haven't been able to reproduce the issues you reported. Could you try again against trunk, and see if the issues are still there?

from django-dynamic-formset.

elo80ka avatar elo80ka commented on July 21, 2024

From stan.madueke on May 03, 2011 17:02:41

(I meant against django-dynamic-formset trunk, not Django trunk :-)

from django-dynamic-formset.

elo80ka avatar elo80ka commented on July 21, 2024

From [email protected] on June 20, 2011 16:15:27

Sorry for the late reply. I'm just back on this project.
So I'm using trunk and it works correctly. Though compared to the example my project needs to use 'formCssClass' on one of the formsets. I cannot figure out why this is the case.
Thanks.

from django-dynamic-formset.

elo80ka avatar elo80ka commented on July 21, 2024

From [email protected] on January 24, 2012 11:22:01

you need formCssClass with multiple formsets because line ~66 when getting the items to update on delete does this:

var forms = $('.' + options.formCssClass).not('.formset-custom-template');

Then renumbers and renames all found forms.

without that, if you delete any of the forms to create "new" items, it will wreak havoc on your names, and lead to a multiple value error.

from django-dynamic-formset.

varun1237 avatar varun1237 commented on July 21, 2024

I am using two forms, while adding the jquery formset is working properly but while deleting it is taking two forms of row values. Please help me to solve this problem.
Html code

Dimension Information
  <div class="panel-body panel-body-diminfo"><table class="test" id="test1">
        <tr>
            <td><label style="text-align:left;">Length</label></td>
            <td><label style="text-align:left;">Breadth</label> </td>
            <td><label style="text-align:left;"><center>Area Square Feet</center></label></td>
        </tr>

  {% for link_editform in edit_form %}
         <tr class="link-dimformset" name="reloadjs" value="Reload JavaScript"  >
             <td onClick="LoadMyJs('/static/bootstrap/dist/js/dimen.js')">{{ link_editform.dimensionX.errors }}{{ link_editform.dimensionX }}</td>
             <td onClick="LoadMyJs('/static/bootstrap/dist/js/dimen.js')">{{ link_editform.dimensionY.errors }}{{ link_editform.dimensionY }}</td>
             <td onClick="LoadMyJs('/static/bootstrap/dist/js/dimen.js')">{{ link_editform.sqft.errors }}{{ link_editform.sqft }}</td>               
        </tr>
        {% endfor %}</table>

  </div>

</div>  
</div>  
<div class="col-lg-4 col-md-6 col-sm-12">
    <div class="panel panel-primary">
  <div class="panel-heading">Installment Breakup</div>
  <div class="panel-body panel-body-inst"><table>
             {% for link_instform in link_installmentset %}
         <tr class="link-installformset" >
                <td > <p >{{ link_instform.installment }}</p> </td>
                <td><p>{{ link_instform.breakup_percent }}</p></td>
                <td><a>%</a></td>
            </tr>
            {% endfor %}
         </table>   </div>
</div></div>

        </div>

jqueryformset.js

;(function($) {
$.fn.formset = function(opts)
{
var options = $.extend({}, $.fn.formset.defaults, opts),
flatExtraClasses = options.extraClasses.join(' '),
totalForms = $('#id_' + options.prefix + '-TOTAL_FORMS'),
maxForms = $('#id_' + options.prefix + '-MAX_NUM_FORMS'),
minForms = $('#id_' + options.prefix + '-MIN_NUM_FORMS'),
childElementSelector = 'input,select,textarea,label,div',
$$ = $(this),

        applyExtraClasses = function(row, ndx) {
            if (options.extraClasses) {
                row.removeClass(flatExtraClasses);
                row.addClass(options.extraClasses[ndx % options.extraClasses.length]);
            }
        },

        updateElementIndex = function(elem, prefix, ndx) {
            var idRegex = new RegExp(prefix + '-(\\d+|__prefix__)-'),
                replacement = prefix + '-' + ndx + '-';
            if (elem.attr("for")) elem.attr("for", elem.attr("for").replace(idRegex, replacement));
            if (elem.attr('id')) elem.attr('id', elem.attr('id').replace(idRegex, replacement));
            if (elem.attr('name')) elem.attr('name', elem.attr('name').replace(idRegex, replacement));
        },

        hasChildElements = function(row) {
            return row.find(childElementSelector).length > 0;
        },

        showAddButton = function() {
            return maxForms.length == 0 ||   // For Django versions pre 1.2
                (maxForms.val() == '' || (maxForms.val() - totalForms.val() > 0));
        },

        /**
        * Indicates whether delete link(s) can be displayed - when total forms > min forms
        */
        showDeleteLinks = function() {
            return minForms.length == 0 ||   // For Django versions pre 1.7
                (minForms.val() == '' || (totalForms.val() - minForms.val() > 0));
        },

        insertDeleteLink = function(row) {
            var delCssSelector = $.trim(options.deleteCssClass).replace(/\s+/g, '.'),
                addCssSelector = $.trim(options.addCssClass).replace(/\s+/g, '.');
            if (row.is('TR')) {
                // If the forms are laid out in table rows, insert
                // the remove button into the last table cell:
                row.children(':last').append('<a class="' + options.deleteCssClass +'" href="javascript:void(0)">' + '<img src="/static/delete.png" >' + '</a>');
            } 
            else if (row.is('UL') || row.is('OL')) {
                // If they're laid out as an ordered/unordered list,
                // insert an <li> after the last list item:
                row.append('<li><a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + '<img src="/static/delete.png">' +'</a></li>');
            } else {
                // Otherwise, just insert the remove button as the
                // last child element of the form's container:
                row.append('<a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + '<img src="/static/delete.png">' +'</a>');
            }               
            // Check if we're under the minimum number of forms - not to display delete link at rendering
            if (!showDeleteLinks()){
                row.find('a.' + delCssSelector).hide();
            }

            row.find('a.' + delCssSelector).click(function() {
                var row = $(this).parents('.' + options.formCssClass),
                    del = row.find('input:hidden[id $= "-DELETE"]'),
                    buttonRow = row.siblings("a." + addCssSelector + ', .' + options.formCssClass + '-add'),
                    forms;
                if (del.length) {
                    // We're dealing with an inline formset.
                    // Rather than remove this form from the DOM, we'll mark it as deleted
                    // and hide it, then let Django handle the deleting:                        
                    del.val('on');
                    row.hide();
                    forms = $('.' + options.formCssClass).not(':hidden');
                } else {
                    alert(totalForms.val());
                    row.remove();                                               
                    // Update the TOTAL_FORMS count:
                    forms = $('.' + options.formCssClass).not('.formset-custom-template');
                    totalForms.val(forms.length);
                }
                for (var i=0, formCount=forms.length; i<formCount; i++) {
                    // Apply `extraClasses` to form rows so they're nicely alternating:
                    applyExtraClasses(forms.eq(i), i);

                    if (!del.length) {
                        // Also update names and IDs for all child controls (if this isn't
                        // a delete-able inline formset) so they remain in sequence:                            
                        forms.eq(i).find(childElementSelector).each(function() {
                            updateElementIndex($(this), options.prefix, i); 

                        });
                    }
                }
                // Check if we've reached the minimum number of forms - hide all delete link(s)
                if (!showDeleteLinks()){
                    $('a.' + delCssSelector).each(function(){$(this).hide();});
                }
                // Check if we need to show the add button:
                if (buttonRow.is(':hidden') && showAddButton()) buttonRow.show();
                // If a post-delete callback was provided, call it with the deleted form:
                if (options.removed) options.removed(row);
                return false;
            });
        };

    $$.each(function(i) {
        var row = $(this),
            del = row.find('input:checkbox[id $= "-DELETE"]');
        if (del.length) {
            // If you specify "can_delete = True" when creating an inline formset,
            // Django adds a checkbox to each form in the formset.
            // Replace the default checkbox with a hidden field:
            if (del.is(':checked')) {
                // If an inline formset containing deleted forms fails validation, make sure
                // we keep the forms hidden (thanks for the bug report and suggested fix Mike)
                del.before('<input type="hidden" name="' + del.attr('name') +'" id="' + del.attr('id') +'" value="on" />');
                row.hide();
            } else {
                del.before('<input type="hidden" name="' + del.attr('name') +'" id="' + del.attr('id') +'" />');
            }
            // Hide any labels associated with the DELETE checkbox:
            $('label[for="' + del.attr('id') + '"]').hide();
            del.remove();
        }
        if (hasChildElements(row)) {
            row.addClass(options.formCssClass);
            if (row.is(':visible')) {
                insertDeleteLink(row);
                applyExtraClasses(row, i);
            }
        }
    });

    if ($$.length) {
        var hideAddButton = !showAddButton(),
            addButton, template;
        if (options.formTemplate) {
            // If a form template was specified, we'll clone it to generate new form instances:
            template = (options.formTemplate instanceof $) ? options.formTemplate : $(options.formTemplate);
            template.removeAttr('id').addClass(options.formCssClass + ' formset-custom-template');
            template.find(childElementSelector).each(function() {
                updateElementIndex($(this), options.prefix, '__prefix__');
            });
            insertDeleteLink(template);
        } else {
            // Otherwise, use the last form in the formset; this works much better if you've got
            // extra (>= 1) forms (thnaks to justhamade for pointing this out):
            template = $('.' + options.formCssClass + ':last').clone(true).removeAttr('id');
            template.find('input:hidden[id $= "-DELETE"]').remove();
            // Clear all cloned fields, except those the user wants to keep (thanks to brunogola for the suggestion):
            template.find(childElementSelector).not(options.keepFieldValues).each(function() {
                var elem = $(this);
                // If this is a checkbox or radiobutton, uncheck it.
                // This fixes Issue 1, reported by Wilson.Andrew.J:
                if (elem.is('input:checkbox') || elem.is('input:radio')) {
                    elem.attr('checked', false);
                } else {
                    elem.val('');
                }
            });
        }
        // FIXME: Perhaps using $.data would be a better idea?
        options.formTemplate = template;

        if ($$.is('TR')) {
            // If forms are laid out as table rows, insert the
            // "add" button in a new table row:
            var numCols = $$.eq(0).children().length,   // This is a bit of an assumption :|
                buttonRow = $('<tr><td colspan="' + numCols + '"><a class="' + options.addCssClass + '" href="javascript:void(0)">' + '<button type="button" class="btn btn-warning btn-xs" style="margin-left:-25px;" >Add</button>' + '</a></tr>')
                            .addClass(options.formCssClass + '-add');
            $$.parent().append(buttonRow);
            if (hideAddButton) buttonRow.hide();
            addButton = buttonRow.find('a');
        } else {
            // Otherwise, insert it immediately after the last form:
            $$.filter(':last').after('<a class="' + options.addCssClass + '" href="javascript:void(0)">' + options.addText + '</a>');
            addButton = $$.filter(':last').next();
            if (hideAddButton) addButton.hide();
        }
        addButton.click(function() {
            var formCount = parseInt(totalForms.val()),
                row = options.formTemplate.clone(true).removeClass('formset-custom-template'),
                buttonRow = $($(this).parents('tr.' + options.formCssClass + '-add').get(0) || this)
                delCssSelector = $.trim(options.deleteCssClass).replace(/\s+/g, '.');
            applyExtraClasses(row, formCount);
            row.insertBefore(buttonRow).show();
            row.find(childElementSelector).each(function() {
                updateElementIndex($(this), options.prefix, formCount);
            });
            totalForms.val(formCount + 1);
            // Check if we're above the minimum allowed number of forms -> show all delete link(s)
            if (showDeleteLinks()){
                $('a.' + delCssSelector).each(function(){$(this).show();});
            }
            // Check if we've exceeded the maximum allowed number of forms:
            if (!showAddButton()) buttonRow.hide();
            // If a post-add callback was supplied, call it with the added form:
            if (options.added) options.added(row);
            return false;
        });
    }

    return $$;
};

/* Setup plugin defaults */
$.fn.formset.defaults = {
    prefix: 'form',                  // The form prefix for your django formset
    formTemplate: null,              // The jQuery selection cloned to generate new form instances
    addText: 'add another',          // Text for the add link
    deleteText: 'remove',            // Text for the delete link
    addCssClass: 'add-row',          // CSS class applied to the add link
    deleteCssClass: 'delete-row',    // CSS class applied to the delete link
    formCssClass: 'dynamic-form',    // CSS class applied to each form in a formset
    extraClasses: [],                // Additional CSS classes, which will be applied to each form in turn
    keepFieldValues: '',             // jQuery selector for fields whose values should be kept when the form is cloned
    added: null,                     // Function called each time a new form is added
    removed: null                    // Function called each time a form is deleted
};

})(jQuery);

assigning add and delete operations

$(function() {
$('.link-dimformset').formset({
addText: 'Add dimension',
deleteText: 'Rem',
prefix: "dim",
})
});
$(function() {
$('.link-installformset').formset({
addText: 'Add Installment',
deleteText: 'Rem',
prefix: "ins",
})
});

from django-dynamic-formset.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.