passing a javascript array to a django view - javascript

I'm using django and have a page of search results that I want to be able to filter by category with ajax (jquery) requests. There's a filter bar on the side of the page and when someone selects certain categories and clicks submit, those corresponding results should show up on the page. My code looks something like this:
<input type="checkbox" name="category1" value="1" />
<input type="checkbox" name="category2" value="2" />
<input type="button" name="submit" onclick="{
var cats = new Array();
$(input[type=checkbox]:checked).each(function() {
cats.push($(this).val());
});
$.getJSON('page.html', {'cats':cats}, function(data) {...});
}" />
But in the django view when I try to read the cats array it returns a 500 error. I can, however, pass scalars and strings to the django view with no problem.
Any thoughts? Is there a more elegant jQuery way to do this without using a javascript array?

Rather than getting the field values manually, you can use jQuery's serializeArray() method, which turns a set of fields into an array which can be sent as JSON. Note that you'll probably want both checkboxes to have the same name, so that when it's serialised it becomes something that Django will interpret as a list.
As Steve says, to help further we'll need to know what the view is doing and what the error is.

Got it working - I downloaded the jquery-json plugin, encoded my array as a json obect to send to django, and then used simplesjon.loads() in the django view to convert that json object to a python list. However, the fact that it took so many steps and jQuery on its own doesn't even come with json encode functionality still makes me think there must be a more elegant way - if anyone has any insight, I'd love to hear it.
Thanks Daniel for pointing me in the right direction.

I guess that a workaround would be transforming your array into a string, eg in javascript:
a = new Array(0,1,2,3,4);
[0, 1, 2, 3, 4]
a.join(" ")
"0 1 2 3 4"
Then you can pass this to the python back end, split it and reconstruct the data structure you need.....

Related

Alternative Way to Pass Checkbox Array to $_GET - Besides Square Braces

I understand that if I use a checkbox value of name[], then I will receive a data array on the server (when using PHP), named 'name[]'. This has worked fine for me, but I'm running into some URL sizes that could cause issues with less robust IE browsers and all the encoded square braces are killing me in this area, easily causing the URL length to be at least 4-6 times longer than what it could possibly be, if another way were available. Is there a reliable method using javascript (jquery syntax even better) to intercept a checkbox forms values and convert them into something like this:
"&checkboxarray=1-23-45-13-67"
I figure that on the other end I can easily explode $_GET['checkboxarray'] into an actual array and go from there as I usually do with matching the selection array against the options array, etc... I just don't know if it's possible or how to create alter the submit process.
Side note, isn't passing "name[]" to a URL non-standards compliant anyways? Every browser I've used auto encodes it, but not Mozilla, however it seems to work fine.
EDIT: I need to create paginated links, which is why I'm using GET, instead of POST. This is also and industrial search, very comprehensive, lots of power user options.
UPDATE & Answer: I managed to come up with my own answer. For anyone else who wants to take advantage of $_GET's easy pagination workflow but you need to pass large data arrays and are worried about URL length, here's a simplistic way to compact it all down into one variable with dash separated values:
NOTE: I HIGHLY suggest you first make sure any dynamic arrays generated from queries start with 1 rather than 0 if your going to recheck values after submit, here's how, since 0 can be a real pain in the neck to work with in PHP conditional statements:
$your_array= array();
array_unshift($your_array,'');
unset($your_array[0]);
In your HTML code, set all checkbox input names to "something[]" and underneath this set of inputs, create a hidden input with the name "something", I suggest you make them match, but I suppose you could use another name, just make sure the hidden one is missing the square braces, also set the hidden input value to "":
<input type="text" name="something[]" value="1">
.....
<input type="text" name="something[]" value="20">
<input type="hidden" name="something" value="">
Javascript: NOTE, requires jquery... this grabs all the "something[]" input values and forms a dashed array while killing off "something[]" values from being submitted and only submitting "something".
$('#submitbutton').click(function(){
var searchIDs = $('input[name="something[]"]:checked').map(function(){
return $(this).val();
}).get();
var IDstring = searchIDs.toString();
var newvar = IDstring.replace(/,/g, '-');
$('input[name="something"]').val(newvar);
$('input[name="something[]"]:checkbox').prop("checked", false);
});
On the server side, simply explode the 'something' value from $_GET.
$somethingArray = explode('-',$_GET['something']);
There it is! Hope it helps someone in the future make their GET sent arrays more compact. Bonus: Avoids sending unsafe characters in the URL, Mozilla doesn't appear to auto encode square braces, at least not my version of it on Linux Mint ;)
Update:
I just implemented this code on a big country checkbox form with 284 possible selections. With my old code, even using 'c[]' as the name, my character count was around 3100 characters, with the new approach, my character count now rings in at just 1109. Worth the effort.
You can use POST instead of GET method.
GET has URL length limitations.
POST is useful in passing long data, e.g. an array in your case.
There is a default limit of POST method which is 2MB which is way higher than GET. If needed, it can easily be increased in php.ini file post_max_size 10MB.
Replace $_GET with $_POST in your script.

Copying a ColdFusion cfparam array into a JavaScript array

I've have a CF page who's inventory search form, frm_inv post's back to itself. frm_inv's main table of records, tbl_inv, uses a tablesorter. A hidden input (sort_list) is used in conjunction with a cfparam to keep track of tbl_inv's sortList:
main.cfm
<cfparam name="form.sort_list" type="string" default="1,0">
<form id="frm_inv" action="main.cfm" method="post">
<input name="sort_list" type="hidden" value="#form.sort_list#"/>
<table id="tbl_inv" class="tablesorter">
...
</table>
</form>
When frm_inv is submitted, CF uses sort_list in $(document).ready() to restore tbl_inv's sort order:
$(document).ready(function(){
var sort_list_str = <cfoutput>"#form.sort_list#"</cfoutput>;
var sort_list = sort_list_str.split(",");
$("#tbl_inv").tablesorter({
textExtraction: ['complex'],
sortList:[[sort_list[0],sort_list[1]]]
}).bind("sortEnd", function(sorter) {
var sl = sorter.target.config.sortList;
$("input[name='sort_list']").val(sl.toString());
});
});
I would rather use arrays than convert a comma separated string into an array like I'm currently doing
<cfparam name="form.sort_list" type="string" default="1,0">
to
<cfparam name="form.sort_list" type="array" default="ArrayNew(2)">
however I need to know the proper javascript and coldfusion syntax in order pose everything that's relevant in arrays exclusively.
Copying a ColdFusion ... array into a JavaScript array
Why? For the most part, HTTP only transmits strings, so there is no translation between client and server complex types. Unless you are doing something more than just passing the sort value back and forth, converting between client and server side arrays is just an unnecessary complication. It is simpler to leave the value as a string and do any splitting or parsing on the client side.
You did not really explain what problem you are trying to solve, but .. there is nothing inherently wrong with the current approach. However, it could be simplified a bit. There is no need to cfoutput the variable again here:
(A) var sort_list_str = <cfoutput>"#form.sort_list#"</cfoutput>;
Since you already stored the current form.sort_list value in a hidden form field, the above is redundant. Instead, just read the field's value with javascript ie
(B) var sort_list_str = $("input[name='sort_list']").val();
Having said that, if you really prefer to work with arrays, you could store a JSON string representation of the arrays instead. Then use parse() and stringify() to convert the arrays back and forth. Same net effect as your current method, but a bit simpler in terms of code.
Form:
<cfparam name="form.sort_list" default="[[1,0]]">
...
<input id="sort_list" name="sort_list"
type="hidden" value="#encodeForHTML(form.sort_list)#" />
...
JQuery:
$(document).ready(function(){
$("#tbl_inv").tablesorter({
textExtraction: ['complex'],
sortList: JSON.parse($("#sort_list").val())
}).bind("sortEnd", function(sorter) {
var sort_arr = sorter.target.config.sortList;
$("#sort_list").val(JSON.stringify(sort_arr));
});
});
For creating a JavaScript variable from a ColdFusion variable, you can use toScript() function.
var #toScript(ListToArray(form.sort_list), "sort_list")#;
This can be used for wide range of variable types such as strings, arrays, structures etc.
Needs specific syntax to use an array in cfparam: ColdFusion CFParam Can Use Struct And Array Notation
<cfparam name="form.sort_list" type="array" default="#ArrayNew( 2 )#">

javascript add array item to form value

I have a form with a hidden field:
<input type="hidden" name="newdesc[]" id="newdesc" />
I have an autolookup and a plus button so the plus button adds the field value of the autolookup to an array:
newdesc_a.push(document.getElementById('autocomplete1').value);
var x=document.getElementById("businesslist");
x.innerHTML=newdesc_a;
document.getElementById('newdesc').value = newdesc_a;
(newdesc_a is previously declared as an array)
It updates the div OK (businesslist) but does not assign the value to the newdesc.
I am sure it is simple but it is driving me mad!
Given the name="newdesc[]" attribute, I assume PHP on the server side. When you submit a key two or more times, only the last value is available in the script via $_REQUEST. In the case of a key ending with [] , instead, PHP builds an array and make it available to your script via $_REQUEST['key']. Note that this behavior is application-specific, there's nothing like an array at the HTTP level.
Now, you want to pass an array from the client side (Javascript) to the backend (PHP). You have two options:
Use a proprietary format, eg separate values by commas or colons, and split the string on the server side (or you can use an existing format like JSON, XML, ...)
Take advantage of the PHP syntax for passing arrays
It seems you want to adopt the 2nd way, so you will want to submit a form like the following
<input name="email[]" value="joel#example.com" />
<input name="email[]" value="mark#people.com" />
<input name="email[]" value="bill#hello.com" />
PHP will be able to access a plain array in $_REQUEST if you build your form like this. Now, you have the problem of building the form programmatically on demand. This is the best I can think of (jQuery):
var email = $("#autocomplete").value;
// if you really need to keep emails in an array, just
// emails.push(email);
$('<input type="hidden">').attr({
name: 'email[]',
value: email
}).appendTo('#myForm');
You want to assign a particular value of array to that element?
You can use like this.
document.getElementById('newdesc').value = newdesc_a.index;
where 'index' is the index of array. replace it.

Expressjs - parsing form array/bracket fields to real arrays

I'd like to either find some existing middleware or some handy code to transform form fields with square brackets (i.e. 'contact[21][name]')into real arrays for ExpressJS 3.
Something along the lines of:
for(key in req.body){
if(key.isArrayField()) {
//add new array field to req.body and delete old string version from req.body
...
I'd like to to parse infinite depth of brackets. I'm still learning JS/Node so would love some direction.
Thanks
Can you provide some clarification about what you're trying to achieve with this?
Depending on how you're getting the input from the web form in the first place you can easily parse JSON syntax into real objects (including arrays) using JSON.parse() (docs here) which is built into node.js
Using that method you can have an infinite level of nested values (hashes / objects, and arrays) but you'll need some client-side script to put the values there in the first place (jQuery for example).
If you give a fuller example, including the context of the form being submitted, I can probably give better direction...
In my experience you can simply do something like this...
Jade
input(type="text" name="foo[]" value="foo1")
input(type="text" name="foo[]" value="foo2")
JS
app.post('/test', function(req,res){
console.log(req.body)// { foo: [ 'foo1', 'foo2' ] }
console.log(req.body.foo)//["foo1","foo2"]
console.log(req.body.foo[0])//foo1
console.log(req.body.foo[1])//foo2
});
I don't know if this makes sense but this is how you treat them... at least on express 3.0+
I've sort of solved this by using https://github.com/marioizquierdo/jquery.serializeJSON - the issue is/was that if I just submit a POST form to express it doesn't handle brackets as an array so they have to be regexed manually. By parsing the form into JSON using the the plugin I can then submit it through ajax.

Search suggestion cache javascript

I am having a Search text-box for which I have to implement a search suggestion(like google search) kind of feature.
for example, if I type "abc" in the search box, I will get suggestions like
abcdef
xyzabcxyz
here each of these unique suggestion represents a jsp page whose url can be "hard-coded" in a java-script array. so when I click any suggested value, the webpage at the corresponding link is displayed.
For this, can you suggest me any efficient methods of implementing this.
This must be in pure javascript, no third-party libs like jquery,etc., can be used
Thanks in advance.
Assuming your data is in an associative JS array similar to this
var locationArray = {
'searchValue1' : 'url1',
'searchValue2' : 'url2',
...
};
and your search input field has a function associated to onkeyup
<input type="text" onkeyup="UpdateSuggestions(this);">
then the rest is simple JavaScript string functions.

Categories