JavaScript/Ajax to Dynamically Update WTForms Select Field - javascript

OK. I know this has been tackled many times but I can't find an answer with a useful example of javascript to use.
Say I have this form:
class MyForm(Form):
category = SelectField("Category")
issue = SelectField("Issue")
What I need is for whatever is selected in 'category' at runtime to determine what the user sees in the issue dropdown without a POST of any kind ocurring. I know how to dynamically create the choices in the view from my database query. I even have gone so far as to create a dictionary of "issue choices" based off of category choices.
I just can't for the life of me figure out the javascript I need so that on select of something from the category drop down determines whats in the issue dropdown.

I found the info I needed by looking at the example at Flask jQuery AJAX Example -
- it is a minimal working example, almost a
GIST or a book chapter.

I came up with an example very close to jsbueno's implementation. You can find the Gist here. The .py file is a standalone example.
In your html template use jquery to register an ajax request when you click the select field. If the request is a success the html for the select field gets updated with the new select options (send as a response from the server). Look at the actual HTML generated by the template to see how the select field looks like.
<form action="" method="post" id="selectDevice" name="device">
Nummber of Devices: {{ form.selectAmount(size=1) }}
Select device: {{form.deviceAddress() }}
</form>
<script type="text/javascript" charset="utf-8">
$("#deviceAddress").click(function(){
$.ajax({
url: '/selectform',
type: 'POST',
data: $('#selectDevice').serialize(),
success: function(selectOptions){
$("#deviceAddress").empty();
for (var i = 0; i < selectOptions.length; i++){
$("#deviceAddress").append(
$("<option></option>")
.attr("value", selectOptions[i][0])
.text(selectOptions[i][1])
);
}
}
});
});
</script>
On the server side, use a route for the ajax post request.`As example this route changes the options depending on another form field (the information got send over with the data tag in the ajax request). In WTForms the select field options is a list of tuples containing an ID and name, I kept this the same on the python side.
#app.route('/selectform', methods=['POST'])
def updateselect():
deviceAmount = int(request.form.get('selectAmount'))
choices = [('device{}'.format(i), i) for i in range(deviceAmount)]
response = make_response(json.dumps(choices))
response.content_type = 'application/jsons'
return response`
Only one remark: the ajax request is performed on dropping down and on collapsing. The last part is not necessary of course, there is probably a way to structure the jquery so it only requests on dropdown.

Related

Can not select a value in my client form and mark it as selected in Silvio Moreto ´s selectpicker

Could you help me? I m working in a client CRUD in PHP, JS and AJAX but I am stuck.
My problem is in client edit form. When I click in edit client, all data of that client is loaded fine into the form, except one of the two selectpicker. I have two selectpicker, one for cities (#idprovincia) and the other for zones (#idmunicipio). When clicking on edit client the procedure should be:
1) Load all cities in #idprovincia selectpicker (works fine)
2) Load all zones of the selected city in #idmunicipio selectpicker (works fine)
3) Select and show as selected the client ´s zone in #municipio selectpicker.
The third point is not working.. I ´ve read about it but I can not find a correct solution for me, so i ´d appreciate your help.
I share my code for showing client data:
function mostrar(idcliente)
{
$.post("../ajax/clientes.php?op=mostrar",{idcliente : idcliente}, function(data, status)
{
data = JSON.parse(data);
mostrarform(true);
$("#idpago").val(data.idpago);
$('#idpago').selectpicker('refresh');
$("#idprovincia").val(data.idprovincia);
$('#idprovincia').selectpicker('refresh');
$("#idmunicipio").val(data.idmunicipio);
//$('#idmunicipio').selectpicker('refresh');
$("#idcliente").val(data.idcliente);
$("#tlfiscal").val(data.tlfiscal);
$("#nombre").val(data.nombre);
$("#zona").val(data.zona);
$("#telefono").val(data.telefono);
$("#movil").val(data.movil);
$("#fax").val(data.fax);
$("#contacto").val(data.contacto);
$("#domicilio1").val(data.domicilio1);
$("#cp").val(data.cp);
var provinciaID=data.idprovincia;
var municipioID = data.idmunicipio;
var data = {'provinciaID': provinciaID};
#this ajax sends client ´s ID to another file and gets the list of zones of a city and loads them into (#idmunicipio) selectpicker
$.ajax({
type:'POST',
url:'../ajax/clientes.php?op=selectMunicipio',
data: data,
contentType: "application/x-www-form-urlencoded",
success: function(data){
$("#idmunicipio").html(data);
$('#idmunicipio').selectpicker('refresh');
}
});
})
#now that I have all zones loaded I want to select the client ´s one and show it as selected in the user interface but this code doesn ´t work...
$("#idmunicipio").val(municipioID);
$('#idmunicipio').selectpicker('refresh');
}`
As you can read from documentation
https://silviomoreto.github.io/bootstrap-select/methods/#selectpickerval
The right way to do this would be
$('.selectpicker').selectpicker('val', 1);
For multiple values you can add array of values
$('.selectpicker').selectpicker('val', [1 , 2]);
So maybe as you select the option you could fill in the hidden input with the actually selected value?
Use on('change') or addEventListener('change') on any of them and fill input with the selected option (choose the value with the :selected selector).
Hope it helps ;)
Problem solved:
Two lines at the end should be:
$('#idmunicipio').selectpicker('val', municipioID);
$('#idmunicipio').selectpicker('refresh');

Create dynamic HTML form using javascript

I've been googling and googling but completely stuck on this.
I have a GET request that retrieves some JSON containing a list of users. However the list of users changes.
I want to generate a simple HTML form that contains the names of the users, and then an input field so that they can be given a rating. I then need to gather the ratings and send a POST request in JSON.
What would be the best way to approach this? I was thinking of looping through the users and just displaying them with a text input type but then I have no idea how I can use the form data to send the POST request!
Any help would be greatly appreciated
Populate UI base on JSON
HTML:
<form id="user_list">
<div>
</div>
<input type="submit"/>
</form>
JS:
var obj = {
users:[{name:"user 1"},{name:"user 2"}]
}
var user_list = $("#user_list>div");
obj.users.forEach(function(user,index){
user_list.append("<div>"+
"<h1>" + user.name + "</h1>"+
"<input type='text' id='user_"+ index +"'/>"+
"</div>");
});
Send selected values to server.
Option 1
If you make this page full post back when click on submit, you have to change text boxes as following
"<input type='text' name='[user_"+ index +"]'/>"+
In server request object, you will be give as array of key/values.
Option 2
If you are planing to make AJAX request, again you can loop though the text boxes and build the JSON format which you want in back-end and pass though the AJAX.
$("input[type='text']").each(function(input){
$(input).val();
});

Load JavaScript model from fields on page

I learned some good things here here
What I want to know if it is possible to load these various JS model values, once the model is converted, from fields on the page without having to use
model.ProductId = $("#txtProductId").val();
What I mean, and this may be a dumb question, is there a way to type in data directly into the JS field? Like the #Html.TextBoxFor to load controller model field for JS variable?
My product form looks somewhat like this:
#model ProductModel
<form id="productForm">
<table>
<tr>
<td>#Html.TextBoxFor(o => o.BrandName, new {#id=txtBrandName})
///etc
One option you have is to use a javascript MVC framework like AngularJS, and then this will happen (more or less) automatically for you. You will probably want to create the text input using plain HTML instead of #Html.TextBoxFor.
For example, if you use AngularJS, your view would look like:
<input type="text" ng-model="model.ProductId" />
This creates a two-way data binding between your text box value and model.ProductId. What this means is that any time the user types a value into the text box, model.ProductId will automatically be set to the new value. Also any time you set model.ProductId in javascript, your text box will automatically update.
As a note, if you have any repeat sections in your view using #for loops, you will probably want to convert them to ng-repeat sections (for AngularJS at least).
I've found the best way to do this with a lot of help from Stephen Muecke. What I do is in the main page I have several DIVs:
<div id="divPerson" style="display: none"></div>
<div id="divProduct" style="display: none"></div>
In the JavaScript code I load each DIV with a partial view:
function loadPerson() {
$.ajax({
type: 'POST',
url: '#Url.Action("LoadPerson"),
success: function(data) {
$("#divPerson").html(data);
$("#divPerson").show();
}
});
And the controller method:
public ActionResult LoadPerson()
{
var model = new PersonModel();
return PartialView("PersonPage", model);
}
And in the PersonPage:
$(document).ready(function() {
$.validator.unobtrusice.parse();
});
And each field in this page has a class of 'personForm'.
This is to read the validation tags again after the page has loaded so that clicking next is this in the main page:
function goNext() {
if (!$("#form1").valid()) {
return false;
}
$.ajax({
type: 'POST',
url: '#Url.Action("AddPerson),
data: $(".personForm").serializeArray(),
success: function(data) {
$("#divProduct").html(data);
$("#divProduct").show();
$("#divPerson").hide();
}
});
I do the same thing for the product page by setting a certain class and serializing those controls to send to the controller.
This, to me, is a good balance between using MVC and jQuery to make the page smooth, crisp, and clean, and enhance the user experience.

Sending a list of values in Jquery to flask template

I am using:
Python 3.4
Flask 10.1
SQLAlchemy 0.9.6
JQuery 2.1.1
I'm working on a forum application that will show a table of forum threads based on tags selected by the user. The tags are a list of on/off buttons generated as per the below Jinja2 template. (Should be around 8, max 16 tags).
<UL class="ForumTagList">
{% for Tag in Forum.ForumTags.filter_by(Visible=True): %}
<li Class="ForumTag VisibleTrue" id ="liTag{{Tag.TagID}}" >
<input id="{{Tag.TagID}}" type="hidden" value="1" name="Name{{Tag.TagID}}"></input>
<DIV class="Tag{{Tag.TagID}}" onclick="toggle_tag('{{Tag.TagID}}');"> {{Tag.Name}}</DIV>
</li>
{% endfor %}
</UL>
There is a JS script that manages the changing of the values to 0 or 1.
The table will be loaded by an AJAX call as per below. It will initially load an unsorted table but the user will be able to refresh to see if new threads appear.
<script type="text/javascript">
$(document).ready(function(){
ThreadTableRefresh();
});
function ThreadTableRefresh(){
$('#ThreadsHolder').load('{{Forum.ForumID}}/ForumThreads');
}
</script>
<div id="ThreadsHolder">
</div>
I understand from reading the documentation on JQuerys Load Method that I can submit a second argument to the .load() method as an object. I hope to submit the on/off values from the users selection, which will then be used to generate the table only showing the tags the user wants.
I am very new to HTML and JQuery, would anyone be able to point me in the right direction as to how to take the various values from those HTML controls and post them as a list or dictionary to a Flask template?
If you need any addition information, please let me know.
You can send a dictionary or json to your flask template. For each TagID, there is a 1 or 0 value, e.g. {1:0, 2:0, 3:1, 4:0}.
Check out the .ajax jquery function to send a json object to your flask route. This should get you started.
Step by step:
click the refresh button
for each tag, add the id and toggle (1/0) value to a dictionary
convert the dictionary to a json object
use ajax function to send the object to your flask route
flask route takes the values, sends back the new html data
the ajax function will substitute the new html upon success
Javascript
$('#refresh-button').click(function() { //selector for refresh button
data = {}
$('input').each(function(){ //might need more specific selector
id = $(this).attr('id')
toggle = $(this).val()
data[id] = toggle
});
data = JSON.stringify(data);
$.ajax({
url: '/YourFlaskRoute'
type: 'POST',
data: data,
contentType: 'application/json;charset=UTF-8',
cache:false,
success: function (response) {
$(".ForumTagList").html(response); //your flask route needs to send back the html for just your list items
},
error: function(response){
alert('Error refreshing forum items')
}
});
});
Flask
#myblueprint.route('/YourFlaskRoute', methods = ['POST'])
def refresh_tags():
if request.method == 'POST':
data = request.json
#access your data
for key, value in data.items():
key = id
value = id
# run your query
tags = ...
#send back your list items template
return render_template('list_items.html', tags = tags)

JQTouch: passing data between 'views'

Hi I have been playing around with jqtouch today and I'm just wondering how to manage data.
I tried looking around but couldn't see much documentation.
If I had a list of links for say products? And I click on one i can navigate to the product 'view'. How to I pass variables like you would a $_GET variable to select THAT product?
Or even if I set the id of the link to the id of the record and use JS to grab the ID and somehow pass it to the next view?
Any help with this would be most appreciated!
NOTE: I also want to use it with the offline extension so I'm not sure get ajax would work
Regards,
Billy
You can use the referrer property for the data object. The link would look like:
Product #1
where the HTML ID would correspond to the product ID. Then in the "pageAnimationEnd" event you can retrieve the product details like this:
$('#view').bind('pageAnimationEnd', function (e, info) {
// get the id of the calling href
var id = $(this).data('referrer')[0].id;
$.getJSON('/products/' + id, function (data) {
// do something with the data
});
});
You could look at the demo to see how it does form submission, i.e. AJAX > POST Form Example. Essentially, you create a form and a jQT-style submit button:
<form id="ajax_demo" action="ajax_demo.php" method="POST" class="form">
...
<a class="submit whiteButton" href="#">Submit</a>
</form>
Then in your receiving page (i.e. ajax_demo.php), you can access the form fields, e.g. PHP's $_GET or JavaScript's location.search.
Another way is to store the data in the DOM with jQuery:
// in global level
$('body').data('ajax_demo', "some data for the page");
// in page/view level
$('#ajax_demo').data('key', 'value');

Categories