Search code examples
javascriptpythoncounterflask-wtformswtforms

Flask wtforms Integerfield() returning NaN


Can someone explain IntegerField() to me? I have searched everywhere and haven't found a good example for what I am looking for. I have a counter on my website; the up-arrow adds 1, the down-arrow subtracts 1. However, when I click either arrow, it just returns NaN, and it wont update. Any ideas?

wtform:

class BetaForm(FlaskForm):
    streak = IntegerField('Streak')
    total = IntegerField('Total')
    submit = SubmitField('Update')

Route

def beta():
    form = BetaForm()
    if form.validate_on_submit():
        current_user.streak = form.streak.data
        current_user.total = form.total.data
        db.session.commit()
        flash('Your account has been updated!', 'success')
    return render_template('betaone.html', form=form)

HTML:

<div class="row">
   <p class="col-12 font100" id="streakcounter">{{ form.streak }}</p>
   <button id="betabuttonplus" onclick="addStreak()"><i class="fa fa-plus"></i></button>
</div>

<form method="POST" action=""> 
  <div class="form-group">
    {{ form.submit(class="my-button btn btn-outline-info") }}
  </div>
</form>

JS

function addStreak() {
    var streak = document.getElementById("streakcounter").innerHTML;
    streak++;
    document.getElementById("streakcounter").innerHTML = streak;
}

Solution

  • The problem here is in javascript:

    document.getElementById("streakcounter").innerHTML
    

    retrieves the entire input element, but we only want to update its value attribute. This function will update the value correctly:

    function addStreak() {
        document.getElementById("streak").value++;
    }
    

    It's possible to avoid having to use javascript to update the form by using an html5 type="number" input; modern browsers will automatically provide up and down arrows ("spinners") to update the value. WTForms provides these inputs in its html5 modules.

    from wtforms import Form
    from wtforms.fields import html5 as h5fields
    from wtforms.widgets import html5 as h5widgets
    
    class MyForm(Form):
        foo = h5fields.IntegerField('foo')
        bar = h5fields.IntegerField('bar', widget=h5widgets.NumberInput(min=1, max=1000, step=5))
    
    form = MyForm()
    for f in form:print(f)
    
    <input id="foo" name="foo" step="1" type="number" value="">
    <input id="bar" max="1000" min="1" name="bar" step="5" type="number" value="">