chhantyal / taggit-selectize

Auto-complete/auto-suggestion for django-taggit (django-taggit + selectize.js)
BSD 3-Clause "New" or "Revised" License
68 stars 23 forks source link

taggit-selectize in templates #16

Open c3959 opened 6 years ago

c3959 commented 6 years ago

hi

this library only works in admin? because when trying to use is a template it does not generate the field in the formual as shown in the image following the documentation.

andytwoods commented 6 years ago

works in the user's frontend. Didn't need to change anything!

brianbola90 commented 6 years ago

@andytwoods what version of django are you using and version of selectize? did you need to include any tags in html template ?

andytwoods commented 6 years ago

afraid I moved to taggit. Indeed, I am pondering whether to move from taggit to ArrayField!

brianbola90 commented 6 years ago

@c3959 see https://github.com/chhantyal/taggit-selectize/issues/17 for solution. Thanks to @andytwoods for the assistance.

c3959 commented 6 years ago

I am using django 1.11.5 and taggit selectize 2.4.0. this message is from the browser console:

jQuery.Deferred exception: $(...).selectize is not a function TypeError: $(...).selectize is not a function at HTMLDocument.

I think it's because jquery is not loaded. this is without modifying anything as recommended above or importing anything in the template. jquery was also tried from the header of the document. jquery is loaded for other script and is available in the console.

andytwoods commented 6 years ago

I had this exact issue yesterday. I was using the widget in a django-filter, and a js and css file were not added to the page. I manually added these and it worked:

{% block javascript %}
  {{ block.super }}
  <script type="text/javascript" src="/static/taggit_selectize/js/selectize.js"></script>
{% endblock %}

{% block css %}
  {{ block.super }}
  <link href="/static/taggit_selectize/css/selectize.django.css" type="text/css" media="all" rel="stylesheet"/>
{% endblock %}
c3959 commented 6 years ago

thanks guys for your guide. has a solution as explained by @andytwoods. I did it by passing the form data to the context of the template.

{% block css %}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
{{ form_media }}

{% endblock css %}

but this patch solution I do not like at all. Now I have two jquery, one in the header and one in the end of the template. I think the problem goes through the input tag script:

Tags
        <script type="text/javascript">
            (function($) {
                $(document).ready(function() {
                    $("input[id=id_tags]").selectize({
                        valueField: 'name',
                        labelField: 'name',
                        searchField: 'name',
                        diacritics: true,
                        create: true,
                        persist: true,
                        openOnFocus: true,
                        hideSelected: true,
                        closeAfterSelect: true,
                        loadThrottle: 300,
                        preload: false,
                        addPrecedence: false,
                        selectOnTab: false,
                        delimiter: ',',
                        plugins: [],
                        render: {
                            option: function(item, escape) {
                                return '<div>' +
                                    '<span class="title">' +
                                        '<span class="name">' + escape(item.name) + '</span>' +
                                    '</span>' +
                                '</div>';
                            },
                            'item': function(item, escape) {
                                name = item.name.replace(/^\s*"|"\s*$/g, '');
                                return '<div class="item">' + escape(name) + '</div>';
                            }
                        },
                        load: function(query, callback) {
                            if (query.length < 2) return callback();
                            $.ajax({
                                url: '/taggit/?query=' + encodeURIComponent(query),
                                type: 'GET',
                                error: function() {
                                    callback();
                                },
                                success: function(res) {
                                    callback(res.tags.slice(0, 10));
                                }
                            });
                        }
                    }).parents('.form-row').css('overflow', 'visible');
                });
            })(jQuery || django.jQuery);
        </script>

                </div>

This script is executed when loading the page, so it asks that the libraries be loaded before in the header. would not it be better to load libraries and then load that script when using the input? or load it after jquery at the end of the document?

andytwoods commented 6 years ago

That script waits for the page to load? Via $(document).ready(function() ... Although it might be wise to use a pure JS way to detect when all the libraries are loaded, including jquery. E.g. document.addEventListener("DOMContentLoaded", function(event){ // your code here });

andytwoods commented 6 years ago

OK, I tried swapping out $(document).ready(function() { with document.addEventListener("DOMContentLoaded", function(event){ (and loading jquery outside of the HEAD) but there's a whole lot of code within selectize.js that now complains about there being no Jquery. Seems best to load jquery in the HEAD and not to bother swapping those 'detect when everything is loaded' listeners.

uditvashisht commented 6 years ago

Could anyone use it outside the admin ? I have tried almost all the methods here and on #17 but couldn't do it.

aventrax commented 6 years ago

Yes, I have it working on a form (django 2.1, taggit, bootstrap 4):

  • Installed taggit-selectize with pip install git+https://github.com/chhantyal/taggit-selectize.git@4cca119f9f0839bdc6bbe9fd0e4fe927f6949a3a (this is only required with Django 2.1, otherwise the pip install taggit-selectize is enough) - Then I followed the instructions on the README.md of this repository
  • myproject/myproject/urls.py: path('taggit/', include('taggit_selectize.urls')) - (curl http://localhost:8000/taggit/?query=mytag must be working)
  • Replaced TaggableManager with the version from this package on my models.py
  • On forms.py (on my ModelForm) I added the widget:
from taggit_selectize import widgets as tag_widget

class PolicyForm(forms.ModelForm):

    class Meta:
        model = Policy

        fields = [
            'name', 'type', 'tags'
        ]

        widgets = {
            'tags': tag_widget.TagSelectize(attrs={'placeholder': 'Tags'}),
        }
  • Loaded jQuery on head, selectize.js and selectize.django.css on the button of the page.
  • Loaded selectize.js and selectize.django.css on the form page
  • My django generic class based view is working without any issue!
chhantyal commented 6 years ago

@aventrax FYI, I released latest from master.

pip install taggit-selectize==2.6.0

jmpark6846 commented 6 years ago

I had this problem and thanks to @andytwoods I solved it somehow (I looked through this chat - https://chat.stackoverflow.com/rooms/176541/discussion-between-andyw-and-sandor-des)

I'm using taggit-selectize in form This is what my head tag looks like.

<head>
...
  {% block css %}
  <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
  {% endblock %}
  {% block javscript %}
    <script src="{% static 'jquery.min.js' %}"></script>
    <script src="{% static 'umd/popper.min.js' %}"></script>
    <script src="{% static 'js/bootstrap.min.js' %}"></script>
  {% endblock %}
  {% block static %}{% endblock %}
...
</head>

and added this code at the bottom of the form page

{% block javascript %}   
  {{ block.super }}  
  <script type="text/javascript" src="/static/taggit_selectize/js/selectize.js"></script> 
{% endblock %}  
{% block css %}   
  {{ block.super }}   
  <link href="/static/taggit_selectize/css/selectize.django.css" type="text/css" media="all" rel="stylesheet"/> 
{% endblock %}

and it worked!

this is my model

from taggit_selectize.managers import TaggableManager

class Document(models.Model):
  ...
  tags = TaggableManager(verbose_name='태그', blank=True)

and this is my form

from taggit_selectize.widgets import TagSelectize

class DocumentForm(forms.ModelForm):

  class Meta:
    widgets = {
    ...
      'tags': TagSelectize(attrs={'placeholder': '태그'}),
    }

FYI Django 2.1 django-taggit 0.23.0 taggit-selectize 2.6.0 "jquery": "^3.3.1"

hope it helps

adhg commented 5 years ago

credits to @jmpark6846 for me I only had to add the below 2 lines and it worked!