yourlabs / django-autocomplete-light

A fresh approach to autocomplete implementations, specially for Django. Status: v4 alpha, v3 stable, v2 & v1 deprecated.
https://django-autocomplete-light.readthedocs.io
MIT License
1.8k stars 468 forks source link

Widget renders on top of previous form when added dynamically #757

Open sid9553 opened 8 years ago

sid9553 commented 8 years ago

Hi, I'm using your autocomplete light widget (very useful by the way!) with django dynamic formsets. At the moment whenever I clone it, it renders the new form on top of the previous one and the dropdown doesn't work properly, very similar to this question on SO http://stackoverflow.com/questions/15500392/django-dynamic-formset-and-django-autocomplete-light-autocomplete-does-not-wor Wondering how to fix this? screen shot 2016-10-07 at 16 47 06

jpic commented 8 years ago

Did you try to call the autocomplete initialization function in an added callback of the formset plugin configuration like in the question in SO ?

sid9553 commented 8 years ago

I tried this

sid9553 commented 8 years ago
sid9553 commented 8 years ago
$(function() {
    $('#myForm tbody tr').formset({
        prefix: '{{ formset.prefix }}',
        added: (function(row) {
            $(row.find('.data-autocomplete-light-function')).each(function(){
                $(this).trigger('autocompleteLightInitialize');
            })
        })
    });
})
sid9553 commented 8 years ago

Same result

jpic commented 8 years ago

It's a bit hard to understand what is going on there. Could you reproduce your issue with minimal code in a new app in the test_project ? Then I could debug this.

sid9553 commented 8 years ago

Alright I'll post it soon as I can

sid9553 commented 8 years ago

Uploading a test version with as minimal code as possible under the folder name autocompletetest

sid9553 commented 8 years ago

I tried uploading it but all uploads are blocked :(, so here's the zip file for the app. It only contains the autocomplete app, with a clone button and some js files, so hopefully it should be easier to decipher. All you've got to do is run it locally.

autocompletetest.zip

sid9553 commented 8 years ago

Any luck Mr Jpic?

jpic commented 8 years ago

Thanks for the reminder !

When your script inserts the cloned element's html then this is triggered:

https://github.com/yourlabs/django-autocomplete-light/blob/master/src/dal/static/autocomplete_light/autocomplete.init.js#L54

And it triggers the duplicate select2 call here: https://github.com/yourlabs/django-autocomplete-light/blob/master/src/dal_select2/static/autocomplete_light/select2.js#L50

Which creates the extra autocomplete input that looks to come from space.

jpic commented 8 years ago

Actually initialisation is called as expected when the select is inserted, which creates a working select2 input next to the hidden select tag.

However, the form clone also includes the the select2 span that was generated initialy for #form_template, it's the second of the line and it doesn't have any callback: clicking on it won't do anything.

jpic commented 8 years ago

Did you try activating the inlines in the admin ?

What result did you get ?

jpic commented 8 years ago

2016-10-17-225808_1037x515_scrot

Verry interresting now !

jpic commented 8 years ago

Did you notice all the clones have the same input name with your script ?

You have this code:

                     html = $("#form_template").clone(true).html().replace(/__prefix_/g, i);

The replace() call doesn't actually change anything, all your selects have the same name.

Try without select2/dal, you'll see your form doesn't work because all form fields have the same name, ie:

<select .... name="form-0-step_option" ... hidden="true">

Try to make the initial form hidden and have a prefix of __prefix__, this can be done with the empty_form property:

https://github.com/django/django/blob/80f5a4d87a6068efe7c04bd9436f0293fbbb4db3/docs/topics/forms/formsets.txt#L250 https://github.com/django/django/blob/3c447b108ac70757001171f7a4791f493880bf5b/django/forms/formsets.py#L197

Like in the admin:

https://github.com/django/django/blob/6f3c78dbe6f17997aa9d115d041bbb0318061ba7/django/contrib/admin/helpers.py#L271

Next time please push on github because it's really bad for me to have a zip i can't explain you as much as if i could show patches and lines of code to you sorry !

At least, there is documentation:

https://github.com/django/django/blob/80f5a4d87a6068efe7c04bd9436f0293fbbb4db3/docs/topics/forms/formsets.txt#L656

jpic commented 8 years ago

It works if you use an empty form for #form_template as such:

<div class = 'table' id="form_template" style="display:none">
    {{ formset.empty_form }}
</div>
<div class = 'table'>
                <table>
<!-- don't use #form_template in your actual form -->

:guitar:

jpic commented 8 years ago

Could you please contribute a documentation page about this ? I'm sure it'll help a lot of our friends ;)

sid9553 commented 8 years ago

Excellent stuff thank you very much. It renders well, but unfortunately doesn't save data as it did when it rendered terribly, I'll try and fix it, and once I do, write some documentation about it.

sid9553 commented 8 years ago

Hi, I'm having a little bit of trouble with changing the id's. I'm a bit of a javascript amateur, and as you said all the clones have identical I'Ds which seems to be stopping them from saving. Only the first form is saved. I've tried a few different things with the replace line in my code, but it hasn't seemed to make any difference. Any suggestions?

jpic commented 8 years ago

I'm sorry, did you try using this code and it didn't work for you ?

<div class = 'table' id="form_template" style="display:none">
    {{ formset.empty_form }}
</div>
<div class = 'table'>
                <table>
<!-- don't use #form_template in your actual form -->

Could you upload your project to github please so that i can push the patch for you .

Thanks !

sid9553 commented 8 years ago

Hi J, I uploaded it to autocompletetest on my profile. Hope it helps. I'll try and find a solution in the meantime, but let me know if there's any issues

jpic commented 8 years ago

There is no manage.py file in your repo.

Could you try to add it and add the commands to run your project and reproduce your issue in the readme please ?

I went through all the reverse engineering when i did it with the zip file, don't have time to go through that again, thanks in advance !

sid9553 commented 8 years ago

Done.

jpic commented 8 years ago

What url should i open to see it ? i remember trying every url last time ^^

sid9553 commented 8 years ago

Just your local http://127.0.0.1:8000/autocomplete/autocompletetest/

jpic commented 8 years ago

I got TemplateDoesNotExist

prodman/basenew.html

sid9553 commented 8 years ago

thats a local template I've got apologies I should've taken that out

sid9553 commented 8 years ago

I've actually sorted the id issue now, but still only one form is saving.

sid9553 commented 8 years ago

managed to fix it and this is how I fixed it