Select2 submits ID instead of TEXT, data via ajax, WTForms, jinja2


#1

I’am trying to implement the Select2 drop-down (data via ajax) feature while using WTForms. Almost everything is working, meaning data is being fetched properly and processed in the expected ‘ID and TEXT’ format that Select2 accepts.

However I am getting a “Not a valid choice” error upon submitting - when validate_on_submit is run. This appears to be caused by the fact that Select2 is submitting the ID number and not the TEXT. This is weird because it is displaying the text on the page itself when searching and selecting. validate_on_submit is expecting 0 or 1 and not a random integer which is why it throws and error. How do I workaround this? How do I get the actual TEXT submitted and not the ID?

I read tons of suggestions and threads on stackoverflow and did come across a couple of similar cases but they had no applicable solution as far as I could tell.

Any help on this is appreciated.

Javascript

Summary
    $(element).parents('.row').find('.item-model').select2({
    placeholder: 'Select an option',
    ajax: {
        url: '/api/1/modelsnew',
        dataType: 'json',
        method: 'GET',
        data: function (params) {
            var specificquery = {
            name: params.term
            }
            return specificquery;
        },
        processResults: function (data) {
        		var res = data.models.map(function (item) {
                	return {id: item.hardware_id, text: item.name};
                });
            return {
                results: res
            };
        },
   },
   minimumInputLength: 2
});

HTML

Summary
    <div class="col-3">
{{ line.item_model.label}}
{% if line.item_model.data == 'Software' %}
{{ line.item_model(class='form-control item-model', disabled=true) }}
{% else %}
{{ line.item_model(class='form-control item-model') }}
{% endif %}
{% for error in line.item_model.errors %}
<p class="form-control-status text-danger">
    {{ error }}
</p>
{% endfor %}
</div>

Flask Form

Summary
    class DeviceForm(FlaskForm):
    item_model = SelectField('MODEL', choices=[('0', 'Select Item')], validators=[DataRequired()])

Here is a GIF just in case it helps https://gifyu.com/image/q8nH

UPDATE:
I found out how to ‘get’ the TEXT value and display it via console.log but how do I make this the selection for the WTForms SelectField ? Why would it register the ID on submit?

var hereitgoes = $(element).parents('.row').find('.item-model')    
$(hereitgoes).on("select2:select", function (e) { 
var selectedtext = $(e.currentTarget).text();
console.log(selectedtext)
});

#2

Select2 uses the item’s “id” value as the “value” attribute of the <option> tags it generates when using a programmatic (AJAX or JS arrray) data source. It seems to me the easiest approach would be to assign the hardware item’s “name” property to the “id” field in the Select2 data. There’s no requirement for the “id” value to be numeric; the only restriction is that it can’t be blank/empty or zero (the number, not a string containing only the digit “0”). As long as each hardware item’s name is unique, the name values should work fine as the “id” values in the Select2 data.

An alternative is to leave your data the way it is, and upon the user making a selection (which you’ve already figured out how to detect), you copy the text value of the selected item into a hidden form field, and validate that field instead of the <select> upon form submission. But I think the first approach I described above should work just fine.


#3

Assigning both the ID and TEXT to the name actually worked! Thank you so much for the prompt reply!


#4

You’re welcome. I’m glad I could help!