Search code examples
javascriptjquerydjangoinline-formset

javascript event handler not correctly work in django inline formset


I designed a inline formset as follows:

class EventForm(ModelForm):
    class Meta:
        model = Event
        exclude = ['created']

class GalleryForm(ModelForm):
    class Meta:
        model= Gallery
        exclude = ['pub_date']
GalleryFormSet = inlineformset_factory(Event, Gallery, extra=0, min_num=1, fields=('title','image' ))

It worked correctly when used 'extra = some number' and saved gallery form data correctly. But when I used javascript handler to add additional gallery form below the main Event form, it creates two Gallery form instead of 1 and data and photo not saved from the newly added form.

Here is my event handler:

<script type="text/html" id="gallery-template">
            <div id="gallery-__prefix__">
                {{ formset.empty_form }}
            </div>
        </script>
        <script>
            $(function() {
                $('.add-photo').click(function(ev){
                    ev.preventDefault();
                    var count = parseInt($('#id_gallery_set-TOTAL_FORMS').attr('value'), 10);
                    var tmplMarkup = $('#gallery-template').html();
                    var compiledTmpl = tmplMarkup.replace(/__prefix__/g, count)
                    console.log(compiledTmpl);
                    $('div.gallery').append(compiledTmpl);
                    $('#id_gallery_set-TOTAL_FORMS').attr('value', count);
                });
            });
    </script>

My formset template:

<form class="form-horizontal" action="" method="post" enctype="multipart/form-data">
                        {{ formset.management_form }}
                        {% csrf_token %}

                        <legend>Events</legend>
                        <div class="author">
                        {{ form.as_p}}
                        </div>

                        <legend>
                            <div class="pull-right"><a href="#" class="btn btn-inverse add-photo"><i class="icon-plus icon-white"></i> Add Photo</a></div>
                            Gallery
                        </legend>
                        <div class="gallery form-inline">
                            {% for form in formset %}
                                {{ form.as_p }}
                            {% endfor %}
                        </div>
                      <div class="form-group">
                        <div class="col-sm-offset-6 col-sm-6">
                            <button type="submit" class="btn btn-success">Submit</button>
                        </div>
                        </div>

                     </form>

For your information, when I edit this formset then data and image saved correctly.

Can anyone indicates the error of my event handler?


Solution

  • I think scripts has error, $('#id_gallery_set-TOTAL_FORMS').attr('value', count);

    line should be:

    $('#id_gallery_set-TOTAL_FORMS').attr('value', count + 1);
    

    Here is workable scripts and template for this problem:

    $(function() {
            $('.add-photo').click(function(ev){
                ev.preventDefault();
                var count = parseInt($('#id_gallery_set-TOTAL_FORMS').attr('value'), 10);
                var tmplMarkup = $('#gallery-template').html();
                var compiledTmpl = tmplMarkup.replace(/__prefix__/g, count)
                console.log(compiledTmpl);
                $('div.gallery').append(compiledTmpl);
                $('#id_gallery_set-TOTAL_FORMS').attr('value', count + 1);
            });
        });
    

    Templates:

    <form action="." method="post" enctype="multipart/form-data">
        {{ formset.management_form }}
        {% csrf_token %}
    
        <legend>Event</legend>
        <div class="event">
        {{ form}}
        </div>
    
        <legend>
            <div class="pull-right"><a href="#" class="btn btn-inverse add-photo"><i class="icon-plus icon-white"></i> Add Photo</a></div>
            Photo Gallery
        </legend>
        <div class="gallery form-inline">
            {% for form in formset %}
                {{ form.as_p }}
            {% endfor %}
        </div>
      <div class="form-actions">
         <button type="submit" class="btn btn-primary">Save</button>
       </div>
     </form>
    

    Hope this help to solve related problems.