3

jquery uiを使用して作成したオートコンプリートウィジェットを使用して、フォームにテキスト入力を入力したいと思います。フォームが送信された場合を除いて、すべてが私が望むように正確に機能します。

問題は、フォームを送信すると、テキスト入力が自動的にリセットされ(理由はわかりません)、その後、フィールドが必要であると表示されてページがリロードされることです(検証が想定どおりに機能するだけです)。もちろん、フィールドをリセットしなければ、すべてうまくいくでしょう。

オートコンプリートの選択イベントが正常に機能しているかどうかはわかりません。コードは次のとおりです。

 select : function (e, ui) {
   // I create a new attribute to store de database primary key of this option. This is
   // usefull later on.
   $('#%(input_id)s').attr('itemid', ui.item.real_value);

   // I set the input text value's.
   $('#%(input_id)s').val(ui.item.label);
 }

オートコンプリートの完全なコードは次のとおりです。

class AutocompleteTextInputWidget (forms.TextInput):

  def media(self):
    js = ("/js/autocomplete.js", "pepe.js")

  def __init__(self, source, options={}, attrs={}):
    self.options = None
    self.attrs = {'autocomplete': 'off'}
    self.source = source
    self.minLength = 1
    self.delay = 0
    if len(options) > 0:
        self.options = JSONEncoder().encode(options)

    self.attrs.update(attrs)

  def render(self, name, value=None, attrs=None):
    final_attrs = self.build_attrs(attrs)        
    options = ''

    if value:
        final_attrs['value'] = escape(value)

    if isinstance(self.source, list) or isinstance(self.source, tuple):
        # Crea un Json con las opciones.
        source = '[' 
        for i in range(0, len(self.source)):
            if i > 0:
                source += ', '
            source += '"' + self.source[i] + '"'
        source += ']'

        options = u'''
            delay : %(delay)d,
            minLength : %(minlength)s,
            source : %(source)s
        '''  % {
               'delay' : self.delay,
               'minlength' : self.minLength,
               'source' : source
        }

    elif isinstance(self.source, str):
        options = u'''
            delay : %(delay)d,
            minLength : %(minlength)s,
            source : function (request, response) {
                if ($(this).data('xhr')) {
                    $(this).data('xhr').abort();
                }
                $(this).data('xhr', $.ajax({
                    url : "%(source_url)s",
                    dataType : "json",
                    data : {term : request.term},
                    beforeSend : function(xhr, settings) {
                        $('#%(input_id)s').removeAttr('itemid');
                    },
                    success : function(data) {
                        if (data != 'CACHE_MISS') {
                            response($.map(data, function(item) {
                                return {
                                    label : item[1],
                                    value: item[1],
                                    real_value : item[0]
                                };
                            }));
                        }
                    },
                }))
            },
            select : function (e, ui) {
                $('#%(input_id)s').attr('itemid', ui.item.real_value);
                $('#%(input_id)s').val(ui.item.label);
            }
        ''' % {
               'delay' : self.delay,
               'minlength' : self.delay,
               'source_url' : self.source,
               'input_id' : final_attrs['id'],
        }
    if not self.attrs.has_key('id'):
        final_attrs['id'] = 'id_%s' % name    

    return mark_safe(u''' 
        <input type="text" %(attrs)s/>
        <script type="text/javascript">
            $("#%(input_id)s").autocomplete({
               %(options)s 
            });
        </script>
    ''' % {
           'attrs' : flatatt(final_attrs),
           'options' :  options, 
           'input_id' : final_attrs['id']
    })

ヒント:オートコンプリートから選択せずにテキストを書き込んだ場合でも、失敗します。

別のヒント:フィールドをオプションとして設定すると、空のビューに到達します。

フォームを送信するときにこの作業を行うにはどうすればよいですか?私はこの仕事をするために何時間も費やしてきました。すでにそのフィールドに入力したことを認識するためのフォームを作成するにはどうすればよいですか?

フォームのコードは次のとおりです。

test = forms.CharField(label = "autotest", widget = AutocompleteTextInputWidget('/myjsonservice'))

これはレンダリングされたhtmlです:

<input type="text"  autocomplete="off" id="id_test"/>
        <script type="text/javascript">
            $("#id_test").autocomplete({

            delay : 0,
            minLength : 0,
            source : function (request, response) {
                if ($(this).data('xhr')) {
                    $(this).data('xhr').abort();
                }
                $(this).data('xhr', $.ajax({
                    url : "/myjsonservice",
                    dataType : "json",
                    data : {term : request.term},
                    beforeSend : function(xhr, settings) {
                        $('#id_test').removeAttr('itemid');
                    },
                    success : function(data) {
                        if (data != 'CACHE_MISS') {
                            response($.map(data, function(item) {
                                return {
                                    label : item[1],
                                    value: item[1],
                                    real_value : item[0]
                                };
                            }));
                        }
                    },
                }))
            },
            select : function (e, ui) {
                $('#id_test').attr('itemid', ui.item.real_value);
                $('#id_test').val(ui.item.label);
            }

            });
        </script>
4

1 に答える 1

3

最後に答えが見つかりました。問題は、「名前」属性がレンダリングされなかったことです。したがって、フィールドはリクエストの一部としてビューに到達できませんでした。

オートコンプリート ウィジェットの最終的なコードは次のようになりました。

class AutocompleteTextInputWidget (forms.TextInput):

    def media(self):
        js = ("/js/autocomplete.js", "pepe.js")

    def __init__(self, source, options={}, attrs={}):
        self.options = None
        self.attrs = {'autocomplete': 'off'}
        self.source = source
        self.minLength = 1
        self.delay = 0
        if len(options) > 0:
            self.options = JSONEncoder().encode(options)

        self.attrs.update(attrs)

    def render(self, name, value=None, attrs=None):
        final_attrs = self.build_attrs(attrs)       
        options = ''

        if value:
            final_attrs['value'] = escape(value)

        if isinstance(self.source, list) or isinstance(self.source, tuple):
            # Crea un Json con las opciones.
            source = '[' 
            for i in range(0, len(self.source)):
                if i > 0:
                    source += ', '
                source += '"' + self.source[i] + '"'
            source += ']'

            options = u'''
                delay : %(delay)d,
                minLength : %(minlength)s,
                source : %(source)s
            '''  % {
                   'delay' : self.delay,
                   'minlength' : self.minLength,
                   'source' : source
            }

        elif isinstance(self.source, str):
            options = u'''
                delay : %(delay)d,
                minLength : %(minlength)s,
                source : function (request, response) {
                    if ($(this).data('xhr')) {
                        $(this).data('xhr').abort();
                    }
                    $(this).data('xhr', $.ajax({
                        url : "%(source_url)s",
                        dataType : "json",
                        data : {term : request.term},
                        beforeSend : function(xhr, settings) {
                            $('#%(input_id)s').removeAttr('itemid');
                        },
                        success : function(data) {
                            if (data != 'CACHE_MISS') {
                                response($.map(data, function(item) {
                                    return {
                                        label : item[1],
                                        value: item[1],
                                        real_value : item[0]
                                    };
                                }));
                            }
                        },
                    }))
                },
                select : function (e, ui) {
                    $('#%(input_id)s').attr('itemid', ui.item.real_value);
                    $('#%(input_id)s').val(ui.item.label);
                }
            ''' % {
                   'delay' : self.delay,
                   'minlength' : self.delay,
                   'source_url' : self.source,
                   'input_id' : final_attrs['id'],
            }
        if not self.attrs.has_key('id'):
            final_attrs['id'] = 'id_%s' % name    

        return mark_safe(u''' 
            <input type="text" name="%(name)s" %(attrs)s/>
            <script type="text/javascript">
                $("#%(input_id)s").autocomplete({
                   %(options)s 
                });
            </script>
        ''' % {
               'attrs' : flatatt(final_attrs),
               'options' :  options, 
               'input_id' : final_attrs['id'],
               'name' : name
        })
  1. 誰かがこの厄介なコードを改善する方法を知っていれば、それは素晴らしいことです.
  2. 誰かがdjango 1.4の素敵なウィジェットのドキュメントを知っていれば(ちなみに公式以外の)それもいいでしょう。

さようなら、皆さん良いコーディング!!!

于 2012-07-26T02:06:57.790 に答える