Skip to content

Commit

Permalink
Form submission related changes
Browse files Browse the repository at this point in the history
  • Loading branch information
deb17 committed Apr 27, 2022
1 parent 7f60326 commit bbca4b4
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 184 deletions.
103 changes: 42 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ Use forms in Bootstrap modals with Flask.
### Description

Plain forms can be boring. Using them in modals is possible, but requires
JavaScript. Normal form submission in modals has its own problems.
JavaScript. Normal form submission in modals is problematic.

This Flask extension eases the process of using forms in Bootstrap modals.
Bootstrap versions 4 and 5 are supported. No JavaScript coding is required on
your part. The JavaScript is handled behind the scenes and uses
html-over-the-wire. You can code in pure Python - flashing messages and rendering
your part. You can code in pure Python - flashing messages and rendering
templates.

### Installation
Expand Down Expand Up @@ -62,7 +61,12 @@ pip install Flask-Modals

You only need to import the function `render_template_modal` in your `routes.py`
file. Use it instead of `render_template` in the route handler for the page with
the modal form. It takes an extra argument - `modal` (the modal `id`).
the modal form. It takes an extra argument - `modal` (the modal `id` with a default
of `modal-form`).
<br>
The extension works by submitting the modal form twice - first via
ajax and then, if all validations pass, normally. When submiited via ajax, it
passes a field '_ajax' with the form, which can be used as shown below.

Example route handler:

Expand All @@ -72,89 +76,66 @@ from flask_modals import render_template_modal
@app.route('/', methods=['GET', 'POST'])
def index():

# Following code is standard in any application
ajax = '_ajax' in request.form # Add this line
form = LoginForm()
if form.validate_on_submit():
if form.username.data != 'test' or form.password.data != 'pass':
flash('Invalid username or password', 'danger')
return redirect(url_for('index'))

if ajax: # Add these
return '' # two lines
login_user(user, remember=form.remember_me.data)

flash('You have logged in!', 'success')
return redirect(url_for('home'))

# Following line is new
return render_template_modal('index.html', form=form, modal='modal-form')
# Add this line
return render_template_modal('index.html', form=form)
```

### Other usage

1. If you want to redirect to the same page outside the modal, use Flask's
`session` proxy:
If you want to render a template and not redirect:

```Python
@app.route('/', methods=['GET', 'POST'])
def index():

flag = session.pop('flag', False)

form = LoginForm()
if form.validate_on_submit():
if form.username.data != 'test' or form.password.data != 'pass':
flash('Invalid username or password', 'danger')
return redirect(url_for('index'))

login_user(user, remember=form.remember_me.data)

flash('You have logged in!', 'success')
session['flag'] = True
return redirect(url_for('index'))

modal = None if flag else 'modal-form'
return render_template_modal('index.html', form=form, modal=modal)
```
<br>
2. If you want to render a template and not redirect:
```Python
@app.route('/', methods=['GET', 'POST'])
def index():

```Python
@app.route('/', methods=['GET', 'POST'])
def index():
ajax = '_ajax' in request.form
form = LoginForm()
if form.validate_on_submit():
if form.username.data != 'test' or form.password.data != 'pass':
flash('Invalid username or password', 'danger')
return render_template_modal('index.html', form=form)

form = LoginForm()
if form.validate_on_submit():
if form.username.data != 'test' or form.password.data != 'pass':
flash('Invalid username or password', 'danger')
return render_template_modal('index.html', form=form, modal='modal-form')
if ajax:
return ''
login_user(user, remember=form.remember_me.data)

login_user(user, remember=form.remember_me.data)
flash('You have logged in!', 'success')
return render_template_modal('index.html', form=form)

flash('You have logged in!', 'success')
return render_template_modal('index.html', form=form, modal=None)
return render_template_modal('index.html', form=form)
```
If the above looks verbose, you can use the `response` decorator and
return a context dictionary, like so:

return render_template_modal('index.html', form=form, modal='modal-form')
```
If the above looks verbose, you can use the `response` decorator and
return a context dictionary, like so:
```Python
from flask_modals import response

```Python
from flask_modals import response

@app.route('/', methods=['GET', 'POST'])
@response('index.html')
def index():
...
...
return {'form': form, 'modal': 'modal-form'}
```
<br>
@app.route('/', methods=['GET', 'POST'])
@response('index.html')
def index():
...
...
return {'form': form}
```
<br>

### Note

1. See the examples folder in the repo for more details.

2. The extension loads the NProgress js library to display a progress bar during
form submission.

3. If you have custom javascript which has global constants, you need to wrap it
in an IIFE. Otherwise, there could be redeclaration errors.
39 changes: 22 additions & 17 deletions examples/bootstrap4/app/routes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from flask import redirect, url_for, flash, session, render_template
from flask import redirect, url_for, flash, session, render_template, request
from flask_login import login_user, logout_user
from flask_modals import render_template_modal, response

Expand All @@ -12,21 +12,23 @@ def index():
is present in a modal.
`render_template_modal` takes the modal id as an argument apart
from the `render_template` arguments.
from the `render_template` arguments. THe default is 'modal-form'.
'''
ajax = '_ajax' in request.form
form = LoginForm()
if form.validate_on_submit():
if form.username.data != 'test' or form.password.data != 'pass':
flash('Invalid username or password', 'danger')
return redirect(url_for('index'))

if ajax:
return ''
login_user(user, remember=form.remember_me.data)

flash('You have logged in!', 'success')
return redirect(url_for('home'))

return render_template_modal('index.html', title='Index page', form=form,
modal='modal-form')
return render_template_modal('index.html', title='Index page', form=form)


# Use the following code if you want to redirect to the same page that
Expand All @@ -35,44 +37,45 @@ def index():
# @app.route('/', methods=['GET', 'POST'])
# def index():

# modal = session.pop('modal', 'modal-form')
# ajax = '_ajax' in request.form

# form = LoginForm()
# if form.validate_on_submit():
# if form.username.data != 'test' or form.password.data != 'pass':
# flash('Invalid username or password', 'danger')
# return redirect(url_for('index'))

# if ajax:
# return ''
# login_user(user, remember=form.remember_me.data)

# flash('You have logged in!', 'success')
# session['modal'] = None
# return redirect(url_for('index'))

# return render_template_modal('index.html', title='Index page', form=form,
# modal=modal)
# return render_template_modal('index.html', title='Index page', form=form)

# Use the following code if you want to render a template instead of
# redirecting.
#
# @app.route('/', methods=['GET', 'POST'])
# def index():

# ajax = '_ajax' in request.form
# form = LoginForm()
# if form.validate_on_submit():
# if form.username.data != 'test' or form.password.data != 'pass':
# flash('Invalid username or password', 'danger')
# return render_template_modal('index.html', title='Index page',
# form=form, modal='modal-form')

# form=form)
# if ajax:
# return ''
# login_user(user, remember=form.remember_me.data)

# flash('You have logged in!', 'success')
# return render_template_modal('index.html', title='Index page',
# form=form, modal=None)
# form=form)

# return render_template_modal('index.html', title='Index page', form=form,
# modal='modal-form')
# return render_template_modal('index.html', title='Index page', form=form)

# Use the following code if you want to render a template instead of
# redirecting and make the code less verbose.
Expand All @@ -81,19 +84,21 @@ def index():
# @response('index.html')
# def index():

# ajax = '_ajax' in request.form
# form = LoginForm()
# if form.validate_on_submit():
# if form.username.data != 'test' or form.password.data != 'pass':
# flash('Invalid username or password', 'danger')
# return {'title': 'Index page', 'form': form,
# 'modal': 'modal-form'}
# return {'title': 'Index page', 'form': form}

# if ajax:
# return ''
# login_user(user, remember=form.remember_me.data)

# flash('You have logged in!', 'success')
# return {'title': 'Index page', 'form': form, 'modal': None}
# return {'title': 'Index page', 'form': form}

# return {'title': 'Index page', 'form': form, 'modal': 'modal-form'}
# return {'title': 'Index page', 'form': form}


@app.route('/home', methods=['GET', 'POST'])
Expand Down
Loading

0 comments on commit bbca4b4

Please sign in to comment.