【问题标题】:Clear all children subcategories of a selected (sub)category in a chained dependent dropdown combobox selection清除链式相关下拉组合框选择中选定(子)类别的所有子类别
【发布时间】:2019-09-29 21:08:26
【问题描述】:

我正在尝试实现链式依赖下拉组合框选择,因此您从一个用于主类别的组合框开始,一旦您选择主类别,就会出现另一个 <select> 用于选择子类别,依此类推,直到最里面(最具体) 子类别被选中。

假设我有两个主要类别,书籍和鞋子,所以如果我选择书籍 -> 教科书 -> 小学,然后我决定选择鞋子,则会出现四个 <selects>s。相反,我想清除所选(子)类别的所有儿童子类别(在这种情况下,两个<select>s(教科书和小学))并让用户仅从主要类别中进行选择。或者,如果我选择书籍 -> 文学,它应该删除小学/高中 <select> 并显示“文学”的子类别。

这是我在 Django 模板中的 jQuery 代码:

{% extends 'pages/base.html' %}

{% block content %}
<h1>Create a product</h1>
<form method='POST' id='productForm' data-products-url="{% url 'products:ajax_load_categories' %}">
    {{ form.as_p }}
</form>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
    var $r_ = function() {
        var url = $("#productForm").attr("data-products-url");
        var categoryId = $(this).val();
        $.ajax({                       
          url: url,                    
          data: {
            'category': categoryId
          },
          success: function (data) {
            if (data != 'leaf_node') {
              $("#productForm").append(data);
            }
            $('select').change($r_);
          }
        });

    } //end of $r_
    $('select').change($r_);
</script>
{% endblock %}

...这是我的观点:

def load_categories(request):
    category_id = request.GET.get('category')
    subcategories = Category.objects.get(id=category_id).get_children()
    if subcategories:
        return render(request, 'products/category_dropdown_list_options.html', {'subcategories': subcategories})
    return HttpResponse('leaf_node')

products/category_dropdown_list_options.html

<select>
    <option value="">---------</option>
    {% for subcategory in subcategories %}
        <option value="{{ subcategory.pk }}">{{ subcategory.name }}</option>
    {% endfor %}
</select>

目前的工作方式是这样的,每当组合框中的值发生更改时,都会触发 AJAX 请求,该请求会调用一个视图,如果某个类别有子级,则该视图呈现另一个 &lt;select&gt;,否则返回一个停止附加侦听器的 HttpResponse。

我正在使用django-mptt 为我的类别建模:

from mptt.models import MPTTModel, TreeForeignKey


class Category(MPTTModel):
    parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
    name = models.CharField(max_length=255)
    slug = models.SlugField()

    class Meta:
        unique_together = (('parent', 'slug',))
        verbose_name_plural = 'categories'

    class MPTTMeta:
        order_insertion_by = ['name']

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        super().save(*args, **kwargs)    

我该如何解决这个问题?

【问题讨论】:

    标签: javascript python jquery django ajax


    【解决方案1】:

    我使用$(this) 来访问当前&lt;select&gt;,我用它来选择下一个&lt;select&gt;s 并在添加新的之前删除它们。它们都必须是兄弟元素才能使其工作:

    $(this).nextAll('select').remove()
    

    因此,要从 AJAX 成功中访问它,我必须将其存储在一个变量中并在回调中使用该变量。

    我还更改了$('select').change($r_) 以使用事件委托,因为我一直这样做的方式会为每次更改多次调用我的函数。因此,我将其更改为:

    $(document).on('change', 'select', $r_);
    

    并删除了成功回调中的 .change() 调用。

    这是工作代码:

    {% extends 'pages/base.html' %}
    
    {% block content %}
    <h1>Create a product</h1>
    <form method='POST' id='productForm' data-products-url="{% url 'products:ajax_load_categories' %}">
        {% csrf_token %}
        <label>Title</label>
        {{ form.title }}
        <label>Description</label>
        {{ form.description }}
        <label>Price</label>
        {{ form.price }}
        <label>Year</label>
        {{ form.year }}
        <label>Category</label>
        {{ form.category }}
        <input type="submit" name="" value="Submit">
    </form>
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <script>
        var $r_ = function() {
            var url = $("#productForm").attr("data-products-url");
            var categoryId = $(this).val();
            var toRemove = $(this).nextAll('select');
            $.ajax({                       
              url: url,                    
              data: {
                'category': categoryId
              },
              success: function (data) {
                if (data != 'leaf_node') {
                  toRemove.remove();
                  console.log(toRemove);
                  $("#productForm").append(data);
                }
                else {
                  toRemove.remove();
                }
              }
            });
    
        } //end of $r_
        $(document).on('change', 'select', $r_);
    </script>
    {% endblock %}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-28
      相关资源
      最近更新 更多