Reputation: 274
Goal: Emulate this example (longtask with bar) with one difference: I need to pass a list of values from the submitted form.
Here's my form.py:
class InstallForm(Form):
servers = SelectField(u'Server Names', validators = [required()])
prop_files = SelectField(u'Properties Files', validators = [required()])
mod_files = SelectField(u'Mod Files', validators = [required()])
build = SelectField(u'Build Type', validators = [required()])
do_install = SelectField(u'Do Install?', validators = [required()])
submit = SubmitField('Submit')
Here are the routes:
User initially comes to /installer
@servers.route('/installer', methods=['GET', 'POST'])
def installer():
servers = UcxServer.query.order_by(UcxServer.name)
file_options = Install(app.config['LOADER_LOCATION']).get_options()
form = InstallForm()
form.servers.choices = [(s.ip_address, s.name) for s in servers]
form.prop_files.choices = [(f,f) for f in file_options['props']]
form.mod_files.choices = [(f,f) for f in file_options['mods']]
form.build.choices = [("'ci'",'ci'), ("'nightly'",'nightly')]
form.do_install.choices = [('TRUE','TRUE'), ('FALSE','FALSE')]
if form.validate_on_submit():
install_list = [form.prop_files.data, form.mod_files.data,
form.build.data, form.servers.data, form.do_install.data]
return render_template('installer.html') <- what to do here?
return render_template('installer.html', form=form)
I'm using wtf.quick_form()
to render this form.
Here's the template where I'm totally lost:
{{ wtf.quick_form(form) }}
<div id="progress"></div>
<script src="//cdnjs.cloudflare.com/ajax/libs/nanobar/0.2.1/nanobar.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
function start_long_task() {
// add task status elements
div = $('<div class="progress"><div></div><div>0%</div><div>...</div><div> </div></div><hr>');
$('#progress').append(div);
// create a progress bar
var nanobar = new Nanobar({
bg: '#44f',
target: div[0].childNodes[0]
});
// send ajax POST request to start background job
$.ajax({
type: 'POST',
url: '/longtask',
data: $('form').serialize()
success: function(data, status, request) {
status_url = request.getResponseHeader('Location');
update_progress(status_url, nanobar, div[0]);
},
error: function() {
alert('Unexpected errorS');
}
});
}
function update_progress(status_url, nanobar, status_div) {
// send GET request to status URL
$.getJSON(status_url, function(data) {
// update UI
percent = parseInt(data['current'] * 100 / data['total']);
nanobar.go(percent);
$(status_div.childNodes[1]).text(percent + '%');
$(status_div.childNodes[2]).text(data['status']);
if (data['state'] != 'PENDING' && data['state'] != 'PROGRESS') {
if ('result' in data) {
// show result
$(status_div.childNodes[3]).text('Result: ' + data['result']);
}
else {
// something unexpected happened
$(status_div.childNodes[3]).text('Result: ' + data['state']);
}
}
else {
// rerun in 2 seconds
setTimeout(function() {
update_progress(status_url, nanobar, status_div);
}, 2000);
}
});
}
$(function() {
$('#button').click(start_long_task);
});
I also have a celery task in my routes, and a redirect route which have a Location header with the task.id
so that I can get status updates.
EDIT1:
To be more specific:
When submit is clicked, the data that is selected in the form should go to:
$.ajax({
type: 'POST',
url: '/longtask',
data: $('form').serialize()
instead of
if form.validate_on_submit():
install_list = [form.prop_files.data, form.mod_files.data, form.build.data, form.servers.data, form.do_install.data]
flash(install_list)
return render_template('installer.html', form=form)
Upvotes: 2
Views: 1850
Reputation: 274
Solved the issue I was having. Here are some highlights for anyone else in the same boat.
abandoned wtf.quick_form New form looks like this:
<form action="" id='ucx'>
{{ form.hidden_tag() }}
<dl>
{{ render_field(form.servers) }}
{{ render_field(form.prop_files) }}
{{ render_field(form.mod_files) }}
{{ render_field(form.build) }}
{{ render_field(form.do_install) }}
</dl>
<p><input type="button" value="Install!" onclick="start_long_task()">
</form>
Instead of using a submit, I'm using a button that links to the long task function. Inside the function I get the values of the form like this:
myArray = [];
myArray.push(document.getElementById('prop_files').value);
myArray.push(document.getElementById('mod_files').value);
myArray.push(document.getElementById('build').value);
myArray.push(document.getElementById('servers').value);
myArray.push(document.getElementById('do_install').value);
I then pass this using AJAX back to the web server like this:
.ajax({
type: 'POST',
url: '/longtask',
data: JSON.stringify(myArray),
contentType: "application/json; charset=utf-8",
dataType: "json",
Hope this helps someone else. By the way, if there is something completely idiotic about the way I'm doing it, I'll be eager to learn.
Thanks!
Upvotes: 2
Reputation: 5682
Although you've added a listener to the user clicking the #button
element, the form will still submit unless you add a handler for that specific action with jquery.submit()
:
$(function() {
$('form').submit(function(event) {
event.preventDefault();
start_long_task();
});
});
Upvotes: 1