Skip to content
This repository

Add select2 constructor parameters #4

Closed
fceruti opened this Issue · 16 comments

2 participants

Francisco Ceruti AppleGrew
Francisco Ceruti

I need to add

createSearchChoice: function(term, data) {
    if ($(data).filter(function() {return this.text.localeCompare(term)===0; }).length===0) {
        return {id:term, text:term};
    }
}

So that I can add stuff, not only select the already existing. Also, I haven't been able to add an initial value to django-select2 form fields.

Are this two things supposed to work but I'm not getting, are bugs or are they not possible?

AppleGrew
Owner

1.
For this you need to sub-class whatever widget you are using. If you are using a field then you need to find out the widget used by it, sub-class that and pass this new widget to that field.

Your widget subclass should override init_options(self). It should be something like below:-

def init_options(self):
    self.options['createSearchChoice'] = JSFunction('Your_js_func_name_here')

Make sure your js function already exists before this widget is rendered. If you need your function to run in context of the rendered select2 field then use JSFunctionInContext instead of JSFunction.

2.
Initial should work as it does with existing fields and widgets. I guess you already tried that, so I will have to check this. Can you tell me which exact widget or field you are trying to use?

AppleGrew
Owner

Maybe you are trying to use a heavy component. I noticed a bug there. It might take a while for me to merge the fix. In the meantime please comment the line self.choices = kwargs.pop('choices', []) in widgets.HeavySelect2Mixin.__init__().

I will close this issue when I merge that fix.

Francisco Ceruti

Awesome, thanks for the tip!

My structure looks like this:

class CityChoices(AutoSelect2Field):
    ...

class MarketChoices(AutoModelSelect2MultipleField):
   widget = MarketWidget

class MarketWidget (AutoHeavySelect2MultipleWidget):
   ...

In both cases, I'm not able to load an initial value.

AppleGrew
Owner

Can you please try with the latest code?

Francisco Ceruti

Ive got:

class CityChoices(AutoSelect2Field):

    def get_results(self, request, term, page, context):
        ...
    def clean(self, value):
        ...

class AddPostForm(forms.ModelForm):
    ...
    city = CityChoices(label=_('City'))
    ...

When I try to display the form, I get the following error:

'NoneType' object is not iterable

This is triggered in line 279 of django_select2/fields.py in _set_choices

self._choices = self.widget.choices = list(value)

Local vars:

self 'utils.fields.CityChoices object'
value 'None'

edit: actually, for some reason, the hole site is down because of this

edit: The work around I found (so that the hole site doesn't crash), is this:

class CityChoices(AutoSelect2Field):
    def __init__(self, *args, **kwargs):
        self.choices = City.objects.none()
        super(CityChoices, self).__init__(*args, **kwargs)
AppleGrew
Owner

Did you try with

if value:
   value = list(value)
else:
    value = []
self._choices = self.widget.choices = value

I hope that would be a better fix. Do you see any issues with that?

Francisco Ceruti

I created a fork with that change, and is not working. Anyway, value is a queryset, so "if value" does a len on it, which is not a good idea considering the whole purpose of this is to not load a huge database

AppleGrew
Owner

Yes. Actually I noticed one design problem. HeavySelect2FieldBase extends Field, but by nature it is a ChoiceField, and it does not have all the necessary code to handle the choices! So, ideally it should extend ChoiceField. I am right now trying that out.

Auto model fields work out well since they eventually extend ModelChoiceField.

AppleGrew
Owner

Can you please check if the branch v3.0.1's code works for you? (https://github.com/applegrew/django-select2/tree/v3.0.1)

Francisco Ceruti

It doesn't crash anymore, but I still can't get initial value. Plus I'm getting an error on heavy_data.js line 183

        callback(data); // Change for 2.3.x

Uncaught TypeError: undefined is not a function

AppleGrew
Owner

This is weird. callback is passed to heavy_data.js from Select2 JS. Can I see the generated Html of your web page somewhere?

AppleGrew
Owner

In addition to the html of the page, can you try the latest code from v3.0.1 branch? I made some fundamental changes to Heavy fields, that should facilitate using big data for these fields. See comments of fields.HeavyChoiceField.

Additionally sine you seem to be using Django models as your data source then why don't you use AutoModelSelect2Field instead? It should take care of many pains and will also normalize to Model object.

Francisco Ceruti

This is the code for my field: http://dpaste.com/hold/795731/ (this explains why I'm not using AutoModelSelect2Field)

This is the generated html: http://dpaste.com/hold/795733/

And this is the error is throws in the js console:

Uncaught TypeError: undefined is not a function heavy_data.js:183
django_select2.onInit heavy_data.js:183
o.initSelection select2.min.js:39
o.init select2.min.js:23
e.fn.select2 select2.min.js:57
e.extend.each jquery-1.7.2.min.js:2
e.fn.e.each jquery-1.7.2.min.js:2
e.fn.select2 select2.min.js:57
(anonymous function) :8000/posts/create-new-post/:225
f.Callbacks.o jquery-1.7.2.min.js:2
f.Callbacks.p.fireWith jquery-1.7.2.min.js:2
e.extend.ready jquery-1.7.2.min.js:2
c.addEventListener.B jquery-1.7.2.min.js:2

The line 225 on /create-new-post/ is:

$('#id_city').data('field_id', '0:2012-09-03 12:50:01.725830');$('#id_city').change(django_select2.onValChange).data('userGetValText', null);$("#id_city").select2({'allowClear': false, 'initSelection': django_select2.onInit, 'multiple': false, 'minimumInputLength': 2, 'minimumResultsForSearch': 6, 'closeOnSelect': false, 'ajax': {'dataType': 'json', 'quietMillis': 100, 'url': '/select2/fields/auto.json', 'data': django_select2.runInContextHelper(django_select2.get_url_params, 'id_city'), 'results': django_select2.runInContextHelper(django_select2.process_results, 'id_city')}, 'placeholder': ''});

Edit: Oh and this error only occurs when I set an inital value to the form

#views.py
def get_initial(self):
    initial = {}
    city = self.request.user.get_profile().city
    print city
    print type(city)
    initial['city'] = city
    return initial
AppleGrew
Owner

From your code I can see that you let user enter multiple values in the field separated by , or space. Why are you not using the Multi value version? Your current use-case of using single value field for multiple values is confusing to me.

I see no issues in the generated Html. Do you have any custom JS code?

Please download the latest v3.0.1 code and retest. Now it will auto pick the non-minimised version of Select2 js, so it should be easier to debug.

I am not sure if this is relevant but note that heavy_data.js uses django_select2.MULTISEPARATOR as the separator among multiple values.

Francisco Ceruti

Thank you so much! I changed CityChoices to AutoModelSelect2Field, and everything is working just fine!

AppleGrew
Owner

Well then I guess we can close this issue. :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.