Roland
Roland

Reputation: 113

How to Connect JQuery-UI Autocomplete Widget to Django-Dajax?

I have a Django app for which I am trying to build an autocomplete UI for making selections. As the user types into a text box and the the app should make search suggestions based on values retrieved from the database. I want to use Dajax/Dajaxice to handle the ajax and the jquery-ui autocomplete widget for the UI template. Can someone please explain how to get the jquery-ui autocomplete widget to call my dajax function via the autocomplete source attribute (or any other better way)?

My code is a combination of this dajax example and this jquery-ui autocomplete example.

my_app/ajax.py:

from my_app.models import MyModel
from dajax.core import Dajax
from dajaxice.decorators import dajaxice_register
from django.utils import simplejson

@dajaxice_register
def auto_filter_selections(request, symbol):
    dajax = Dajax()
    result = MyModel.objects.filter(symbol__startswith = symbol)
    dajax.assign('#id_symbol', 'innerHTML', str(result))
    return dajax.json()

template: my_app_ui.html

<head>
....
<script type="text/javascript" src="{{STATIC_URL}}jquery/jquery-1.7.2.js"></script>
<script type="text/javascript" src="{{STATIC_URL}}dajax/jquery.dajax.core.js"></script>
<script type="text/javascript" src="{{STATIC_URL}}/jquery/jquery-ui-1.10.4.custom/js/jquery-ui-1.10.4.custom.js"></script>
....
<script>
  $(function() {
    $("#id_symbol").autocomplete({
      source: "Dajaxice.ui.auto_filter_symbols(Dajax.process,'symbol':$('#id_symbol').serialize(true)});",
      minLength: 1 //We want to search for even one character
    });
  });
</script>
....
</head>

<body>
....
<div class="ui-widget">
  <label for="id_symbol">Symbol: </label>
  <input id="id_symbol">
</div>
....
</body>

If you notice above, I am using jquery-1.7.2 and jquery-ui-1.10.4. This is because the dajax documentation says it is compatible with jquery-1.7.2. Not sure if I can use a newer jquery version.

I am not sure how to get the template's javascript to call my dajax function. the jquery-ui documentation for .autocomplete says to use its source attribute but does not give a very good example. Can anyone tell me if the above is correct?

Once the dajax view function retrieves suggestions from the DB, how do I populate the .autocomplete text box with it?

I've done quite a bit of research over the past few days but there are few examples of Django-Dajax-JQueryUI applications out there.

Upvotes: 0

Views: 1480

Answers (1)

Roland
Roland

Reputation: 113

After considerably more research and piecing various clues together I finally found the key to getting the JQuery-UI autocomplete widget to work with Dajax/Dajaxice and Django.

Synopsis:

  1. Initialize JQuery-UI .autocomplete's source option with a separate javascript (JQuery) setter function
  2. Connect .autocomplete widget's source option to server-side function with a Dajaxice command via a third javascript function.

Explanation:

Firstly, it is important to remember that Dajaxice provides the ajax communication channel by which your client-side javascript and the server side code transact, whereas Dajax provides a convenient way of generating the javascript (JSON) code that will perform the desired function in the client browser without having to write any javascript.

Since JQuery-UI provides us with the javascript widget (in the form of jquery) to perform our desired function (.autocomplete), we do not need Dajax and will not, according to my findings, have any success with it in this application. We ONLY need Dajaxice in order to connect the client side javascript (.autocomplete) to our server side function that does the searching and returns results to suggest to the user.

Below is my revised code that I have gotten working. Note that I have only tested it on a development platform thus far.

my_autocomplete_search_template.html with extraneous code removed:

<head>
....
<script type="text/javascript" src="{{STATIC_URL}}jquery/jquery-1.7.2.js"></script>
<script type="text/javascript" src="{{STATIC_URL}}dajax/jquery.dajax.core.js"></script>
<script type="text/javascript" src="{{STATIC_URL}}/jquery/jquery-ui-1.10.4.custom/js/jquery-ui-1.10.4.custom.js"></script>
....
<script>
    //Initialize the source option of .autocomplete widget during page load
    //See: http://api.jqueryui.com/autocomplete/#method-option setter example code
    var local_source = ["Abc",]  //Dummy string for initialization only; temporary value
    $("#search_box").autocomplete("option", "source", local_source)
</script>
<script>
    //.autocomplete widget is Dajaxice callback function
    // *data* comes from server-side function
    function search_result(data) {
        $("#search_box").autocomplete({
            source: data,
        });
    }
</script>
<script>
    //This function called by user <input> tag and calls the server-side function via Dajaxice command
    function dajax_filter_search_term() {
        Dajaxice.my_app.auto_filter_search_term(search_result,'search_term':$('#search_box').val()});
        //                  |                     |                  |      ----------------------
        //                  |                     |                  |                |
        //             server-side          .autcomplete      serverside          user-typed
        //              function           callback func.    func. argument      value to search
    }
</script>
....
</head>

<body>
....
<div class="ui-widget">
    <label for="search_box">Search Term: </label>
    <input type="text" name="search" id="search_box" onkeyup="dajax_filter_search_term()" />
</div>
....
</body>

my_app/ajax.py

from dajaxice.decorators import dajaxice_register
from django.utils import simplejson
from my_app.models import MyModel

@dajaxice_register
def auto_filter_search_term(request, search_term):
    # Query DB for suggestions to present to user
    q = MyModel.objects.filter(myfield__istartswith=search_term)
    data = []
    for item in q:
        # Format returned queryset data, if needed
        data_item = item.field1 + ', ' + item.field2 + ', ' + item.field3
        data.append(data_item)

    # Return data to callback function *search_result*
    return simplejson.dumps(data)

That is it! The key is to initialize the .autocomplete source option first and to only use Dajaxice to communicate with the server-side function.

It is possible to optimize the client-side code further by getting rid of the javascript function dajax_filter_search_term() and including the Dajaxice call in the #search_box input tag like so:

<input type="text" name="search" id="search_box" onkeyup="Dajaxice.ui.auto_filter_search_term(search_result, {'search_term':$('#search_box').val()})" />

References

Upvotes: 0

Related Questions