Reputation: 87
I'm using Django Crispy Forms and in my creation form, I'd like my users to select one category in a select dropdown and then I want to fetch all features related to that category and display all the features in check boxes below. I figured ajax/Jquery makes sense for that, so I came up with the following:
My View:
def show_category_feature_set(request):
category_id = request.GET.get('category')
category = Category.objects.get(id=category_id)
features = category.features.all().values('name', 'id')
response_data = {}
try:
response_data['features'] = list(features)
except:
response_data['error'] = "Sorry, couldn\'t load any features"
return JsonResponse(response_data)
My Model:
class Feature(models.Model):
name = models.CharField(max_length=100, blank=False)
class Category(models.Model):
name = models.CharField(max_length=50, blank=False)
slug = models.SlugField(unique=True)
features = models.ManyToManyField(Feature, through='FeatureCategorization' )
class FeatureCategorization(models.Model):
category = models.ForeignKey(Category)
feature = models.ForeignKey(Feature)
Here is my form:
class ListingForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(ListingForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_id = 'listing'
self.helper.form_show_errors = True
self.helper.form_method = 'post'
self.helper.form_action = 'submit'
self.helper.add_input(Submit('submit', 'Submit'))
class Meta:
model = Listing
fields = ['title', 'event_types', 'category', 'features', 'description', 'blog_url', 'website', 'pricing_page']
widgets = {
'event_types': forms.CheckboxSelectMultiple(),
'features': forms.CheckboxSelectMultiple()
}
And here is the html that my Django Crispy Form (Model Form) generates. I need to create this block dynamically, so the checkboxes below need to be shown based on the previous select.
<div class="form-group" id="div_id_features">
<label class="control-label requiredField" for="id_features_0">Features<span class="asteriskField">*</span></label>
<div class="controls" id="listing">
<div class="checkbox">
<label class=""><input id="id_features_1" name="features" type="checkbox" value="10">Online Registration</label>
</div>
<div class="checkbox">
<label class=""><input id="id_features_2" name="features" type="checkbox" value="11">PCI Compliance</label>
</div>
</div>
</div>
Here is the AJAX which does everything correctly, but doesn't produce the correct HTML.
$( "#id_category" ).change(function () {
var category = $( this ).val();
$.ajax({
url: '/ajax/category_features/',
data: {
'category': category
},
dataType: 'json',
success: function ( response_data ) {
$("#div_id_features").empty().append(response_data.features.map((feature) => {
return $('<input >', {
type : 'checkbox',
id: 'id_features_' + feature.id,
name: 'features',
value: feature.id,
}).wrap("<label > </label>").text(feature.name);
}));
}
});
});
The above generates the following (it basically shows two empty checkboxes, not formated, not labelled).
<div id="div_id_features" class="form-group">
<input type="checkbox" id="id_features_10" name="features" value="10">
<input type="checkbox" id="id_features_11" name="features" value="11">
</div>
I really don't know if I'm approaching the problem right. What's the easiest way to dynamically create checkboxes based on previous select dropdown? What's wrong with my Jquery? As you can probably tell, I'm a beginner. How would you guys do it? What's wrong with my approach? Any help would be greatly appreciated.
Upvotes: 1
Views: 1841
Reputation: 96
it's is how .wrap works, it appears the element must in the DOM to work, but anyway, there's no need to wrap it at all, u can just create whatever u want inside the map.
an example here - https://jsfiddle.net/oborudko/eo5x0unr/
$('#features').empty().append(features[$(this).val()].map(feature => $('<div class="checkbox"><label>' +
'<input type="checkbox" name="features[]" value="' + feature.id + '"/>' + feature.name +
'</label>')
));
});
Upvotes: 2