Autocomplete TextInput Widget w/ Static Data (jQuery UI)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# widgets.py
from django.forms.widgets import TextInput, flatatt
from django.forms.util import force_unicode
from django.utils.html import escape
from django.utils import simplejson
from django.utils.safestring import mark_safe


class AutocompleteInput(TextInput):
    """
    A form text input that gets rendered as an autocomplete widget using
    jQuery UI's autocomplete.

    http://api.jqueryui.com/autocomplete/

    The only required option is choices:

    class FooForm(forms.Form):
        selections = forms.CharField(max_length=10, widget=AutocompleteInput(choices=MY_SELECTIONS))
    """
    def __init__(self, choices, options={}, attrs={}, *args, **kwargs):
        super(TextInput, self).__init__(attrs=attrs, *args, **kwargs)
        self.choices = choices
        self.options = simplejson.dumps(options) if len(options) > 0 else None
        self.attrs = attrs

    def render(self, name, value=None, attrs={}):
        final_attrs = self.build_attrs(attrs, name=name)

        # Handles different types of choices
        if isinstance(self.choices, list):
            source = simplejson.dumps(self.choices)
        elif isinstance(self.choices, str):
            source = "'{0}'".format(escape(self.choices))
        elif isinstance(self.choices, tuple):  # assumes tuple will be 2-item choice tuples (as in the docs)
            try:
                ## This sets the displayed values
                # If you have (for example) "fruit" tuples like (('apples', 'apples'),), then you can
                # just use item[0] for the "label"
                # The below set up is useful for displaying the human-readable format, and inserting
                # the value that will go into the database. For instance, (('FL', 'Florida'),) will
                # display "Florida" but insert "FL" into the field.
                source = simplejson.dumps([{"label": "{0}".format(item[1]), "value": "{0}".format(item[0])} for item in self.choices])
            except IndexError:
                raise ValueError("choices tuple is not valid")
        else:
            raise ValueError("choices type is not valid")

        options = ''
        if self.options:
            options += ",{0}".format(self.options)  # for passing add'l autocomplete options

        if value:
            value = force_unicode(value)
            final_attrs['value'] = escape(value)
        if not self.attrs.has_key('id'):
            final_attrs['id'] = 'id_{0}'.format(name)
        return mark_safe(u'''<input type="text" name="{0}" id="{1}" {2}>
                <script type="text/javascript">
                    $('#{1}').autocomplete({{source:{3}{4}}});
                </script>'''.format(name, flatatt(final_attrs), final_attrs['id'], source, options))

## EXAMPLE
# 
# forms.py
# 
from django.contrib.localflavor.us.us_states import US_STATES, US_TERRITORIES

from .widgets import AutocompleteInput


class ResidentForm(forms.ModelForm):
    ALL_STATES = tuple(sorted(US_STATES + US_TERRITORIES, key=lambda obj: obj[1]))
    ...
    state = forms.CharField(max_length=2, widget=AutocompleteInput(choices=ALL_STATES)  # just use {{ form.state }} in template
    ...

More like this

  1. jquery autocomplete widget by skam 6 years, 11 months ago
  2. jQuery Autocomplete by zeeg 6 years, 10 months ago
  3. Django JQuery Autocomplete for Model Selection by elpenia 5 years, 6 months ago
  4. Select Dropdown Widget with jQueryUI by maguspk 3 years, 9 months ago
  5. Multiple Select Widget with jQueryUI by maguspk 3 years, 9 months ago

Comments

oz123 (on May 29, 2013):

This script seems not to work. Can you show what you included in your base template also ?

#

(Forgotten your password?)