1

Let's say I have a simple DAL autocomplete & form rendering custom html results, where the result contain data-attribute.

from django.utils.html import format_html

class CountryAutocomplete(autocomplete.Select2QuerySetView):
    def get_result_label(self, item):
        return format_html('<span data-url="{}">{}</span>', item.get_dashboard_url(), item.name)


class CountryForm(forms.Form):
    country = forms.ModelChoiceField(
        queryset=Country.objects.all(),
        widget=autocomplete.ModelSelect2(
            url="country-autocomplete",
            attrs={
                "data-result-html": True,
            },
        ),
    )

Now on select I want to get the data attribute of the selected item.

$(document).ready(function() {
  $('#id_country').on('select2:select', function(e) {
    // get the selected item data attributes.
  });
});

I've tried $(this).find(":selected").data('url'). But it returns undefined

Todor
  • 15,307
  • 5
  • 55
  • 62

1 Answers1

1

OK, after digging a little bit more I found two solutions which I'm gonna paste here in case someone else is having the same problem.

So the problem here is that $(this).find(":selected") returns the option but it has no data attributes because all the html is inside its text attribute ($(this).find(":selected").text() returns the markup.);

Solution 1

So the first solution is do the following (I'm not sure what jQuery do behind the scenes here, it probably parse the markup and creates an object from it).

$($(this).find(":selected").text()).data('url')

Solution 2

Another thing which I notice is that $(this).find(":selected").data() returns the data which select2 gets from the ajax call. So we can alter our View to return more data.

class CountryAutocomplete(autocomplete.Select2QuerySetView):
    # ... get_result_label()
    def get_results(self, context):
        """Return data for the 'results' key of the response."""
        return [
            {
                "id": self.get_result_value(result),
                "text": self.get_result_label(result),
                "url": result.get_dashboard_url(),
                "selected_text": self.get_selected_result_label(result),
            }
            for result in context["object_list"]
        ]

And now in the Javascript we can go with:

$(this).find(":selected").data().data.url
Todor
  • 15,307
  • 5
  • 55
  • 62