Skip to content
This repository has been archived by the owner on Nov 9, 2019. It is now read-only.

How to make it dynamic ? #23

Open
isasiluis28 opened this issue Nov 27, 2016 · 1 comment
Open

How to make it dynamic ? #23

isasiluis28 opened this issue Nov 27, 2016 · 1 comment

Comments

@isasiluis28
Copy link

isasiluis28 commented Nov 27, 2016

I'm struggling with making it dynamic, like with jquery formsets, but that plugin wont work out of the box, how can I do it then ? thank you

@skiv23
Copy link

skiv23 commented Sep 13, 2017

Hi, this is the answer for someone like me who decided to make it dynamic.

I've faced this issue when it was required for me to build a "Bar chart builder" so that a user could place multiple charts with customizable rows on the page along with other ordinary formsets.

I've been using underscore.js since the first time I faced dynamic formsets and I came up with generic function which will be described below along with HTML code.

HTML:

{{ chart_formset.management_form }}
<div id="chart_container">
    {% for chart in chart_formset %}
    <div class="formsetForm">
        {{ chart|crispy }}
        {{ chart.nested.management_form }}
        <div id="chart_row_container_{{ forloop.counter0 }}">
            {% for chart_row in chart.nested %}
            <div class="formsetForm">
                {{ chart_row|crispy }}
            </div>
            {% endfor %}
        </div>
	<!-- data-counter is required for our function to know to which container it should append a form —>
        <input type="button" data-formset="chart_row" data-counter="{{ forloop.counter0 }}"
               value="Add Chart Row" class="btn btn-success add-formset"/>
    </div>
    {% endfor %}
</div>
<input type="button" data-formset="chart" value="Add Chart" class="btn btn-success add-formset"/>

JS:

{{ block.super }} // jQuery, etc.
{{ chart_formset.empty_form.nested.empty_form.media }}
<script src="{% static 'lib/underscore-min.js' %}"></script>
<script type="text/html" id="chart-template">
    <div class="formsetForm">
        {{ chart_formset.empty_form|crispy }}

	// we need to add a management form for each nested formset
        {{ chart_formset.empty_form.nested.management_form }}
        <div id="chart_row_container___prefix__"></div>
        <input type="button" data-formset="chart_row" data-counter="__prefix__" value="Add Chart Row" class="btn btn-success add-formset"/>
    </div>
</script>
<script>
    addFormsetForm = function (ev, formset_name) {
        ev.preventDefault();

        var formset = $(this).data('formset') || formset_name,
            formsetSplit = formset.split('_'),
            counter = $(this).data('counter'),
            $container = typeof counter != 'undefined' ? $('div#' + formset + '_container_' + counter) : $('div#' + formset + '_container'), // find the container
            count = $container.children().length,
            tmplMarkup = $('#' + formset + '-template').html(), // find the template
            compiledTmpl;

	// compile our template
        if (typeof counter != 'undefined') {
            compiledTmpl = tmplMarkup.replace(
                new RegExp('__prefix__-' + formsetSplit[1] + 's-__prefix__', 'g'),
                counter + '-' + formsetSplit[1] + 's-' + count
            ).replace(/__num__/g, count + 1);
        }
        else
            compiledTmpl = tmplMarkup.replace(/__prefix__/g, count).replace(/__num__/g, count + 1);
	
        $container.append(compiledTmpl);

	// bind mouse click on newly created “Add formset” button
        $container.find('.add-formset[data-counter=' + count + ']').click(addFormsetForm);

        // update form count
        var id;

        if (typeof counter != 'undefined')
            id = formsetSplit[0] + 's-' + counter + '-' + formsetSplit[1] + 's'
        else
            id = formset + 's';

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

    };

    $('.add-formset').click(addFormsetForm);
</script>

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants