Select2 parameter for templateResult and templateSelection different (django)

I have a weird problem. I have a product picker item in my web application. Since there are quite a few products in the database, I decided to load them dynamically using select2. The problem is that I want to pass an additional parameter (Unit) that will be displayed opposite the select box. So to find a product I am using Django as my backend and my method looks like this.

class FindProductAjaxView(AjaxableResponseMixin, CreateView):
    model = Product
    form_class = ProductForm

    def get_ajax(self, request, *args, **kwargs):
        query = request.GET.get('q', None)
        if query:
            products = Product.objects.filter(name__icontains=query).values(
                "pk", "name", "unit")
            results = list(products)
            return JsonResponse(data={'items': results}, safe=False)
        else:
            return JsonResponse(data={'success': False,
                                      'errors': 'No mathing items found'})

      

This way it correctly returns the pk, name and unit fields. Here is the script I am using to create my select2 product inputs.

<script>
    function initProductSelect2 (select) {
        select.select2({
            placeholder: "Wyszukaj...",
            ajax: {
                url: '/recipes/find_product',
                dataType: 'json',
                delay: 250,
                language: 'pl',
                data: function (params) {
                  return {
                    q: params.term, // search term
                    page: params.page
                  };
                },
                processResults: function (data) {
                    data = data.items.map(function (item) {
                        return {
                            id: item.pk,
                            text: item.name,
                            name: item.name,
                            unit: item.unit
                        };
                    });
                    return { results: data };
                },
                cache: true
          },
          escapeMarkup: function (markup) { return markup; },
          minimumInputLength: 1,
          templateResult: formatItem,
          templateSelection: formatItemSelection
        });
        select.siblings('span').find('.select2-selection').addClass('form-control');
    }

    function formatItem (item) {
        console.log(item)
        if (item.loading) return item.name || item.text;
        var markup = '<div class="clearfix" data-unit=' + item.unit + '>' + item.name + '</div>';
        return markup;
    }

    function formatItemSelection (item) {
        console.log(item);
        return item.name || item.text;
    }
</script>

      

The problem lies in the methods formatItem

and formatItemSelection

. The item passed to formatItem

is ok. I have all the fields I need (pk, name, unit). But the element that goes into formatItemSelection

only has id and text boxes.

I have been struggling with this problem for hours now, but I have no idea. I tried (as you can see in the code) passing the unit parameter as a jQuery data item, but I don't know how to get it. The best solution would be if the element passed to formatItemSelection

had all the fields passed from the controller (pk, name, unit).

Thanks in advance!

EDIT: I am using select2 in the newest 4.0.3

+3


source to share


1 answer


Ok, I have an answer. In the context of initProductSelect2 (), I create an object options

that populates in ProcessResults

, and then I retrieve my parameter there when the select event is called. I also changed the processResults method. Here's my updated code with a warning showing the unit of the selected product. I initialize my select2 as before, but with a second parameter like this initProductSelect2(select, [])

:



function initProductSelect2 (select, options) {
        select.select2({
            placeholder: "Wyszukaj...",
            ajax: {
                url: '/recipes/find_product',
                dataType: 'json',
                delay: 250,
                language: 'pl',
                data: function (params) {
                  return {
                    q: params.term, // search term
                    page: params.page
                  };
                },
                processResults: function (data, params) {
                    params.page = params.page || 1;
                    data.items.forEach(function (entry, index) {
                        entry.id = entry.pk;
                    });
                    options = data.items;
                    return {
                        results: data.items,
                        pagination: {
                            more: (params.page * 30) < data.total_count
                    }
                  };
                },
                cache: true
          },
          escapeMarkup: function (markup) { return markup; },
          minimumInputLength: 1,
          templateResult: formatItem,
          templateSelection: formatItemSelection
        });
        select.on("select2:select", function(e) {
            var id = $(this).val();
            var result = $.grep(options, function(e){ return e.id == id; });
            if (result.length != 0) {
                alert(result[0].unit);
            }
        });
        select.siblings('span').find('.select2-selection').addClass('form-control');
    }

      

+1


source







All Articles