Search code examples
djangoformsonchangetextinput

Django - get value of a form textinput on onchange event


I am using this to get the ID and the value of a select item in a form in django with the onchange event:

class forms_bdc(forms.ModelForm):
[...]
    bdc_description_1 = forms.ModelChoiceField( widget=forms.Select(attrs={'id': 'editable-select-2','onchange': 'populate_selected_product(this.id,this.value)'}),empty_label=None )

I am trying to do the same with a TextInput widget. The ID is returned as expected but I don't know how to get the value :

   bdc_quantity_1 = forms.CharField( widget=forms.widgets.TextInput(attrs={'onchange':'calculate_price_of_product(this.id,this.value)'}))

I also tried with this.text instead of this.value but no success.

Thanks


Solution

  • The behavior of the event is sometimes specific, especially in the case of onchange, because there is a race condition between the browser and your code to try to resolve the value.

    The first approach is to use a Timeout before calling calculate_price_of_product. The delay can be 0, but the function will be called after the event. For example:

    attrs={'onchange': 'let input=this; setTimeout(function() {populate_selected_product(input.id,input.value)},0);}'}
    

    This is usuall practice, you can search here, on SO by "is setTimeout(fn, 0) useful?"

    The other way in Django to do, what you want, is to use raw event change in js:

    class BdcForm(forms.Form):
    
        class Media:
            js = ('bdcs/js/onchange.js',)
        
        ...
        bdc_quantity_1 = forms.CharField()  # I dont use any widget
    

    and onchange.js seems like:

    window.addEventListener('load', function () {
        document.getElementById('id_bdc_description_1').addEventListener('change', function() {
            console.log('You selected: ', this.id, this.value);
        });
    })
    

    I called it better way because in Django the window.onload event is often used, and in django-admin there are many js.scripts "in the box" running on window.onload.