Reputation:
Just wondering if there is anything built-in to Javascript that can take a Form and return the query parameters, eg: "var1=value&var2=value2&arr[]=foo&arr[]=bar..."
I've been wondering this for years.
Upvotes: 275
Views: 348538
Reputation: 11185
Using URL and URLSearchParams
let url = new URL("https://foo.bar");
url.search = new URLSearchParams({
customerid: 12345,
lang: "en"
}).toString();
console.log(url.toString());
Upvotes: 2
Reputation: 6743
Remove undefined params 💪😃
urlParams = obj =>{
const removeUndefined = JSON.parse(JSON.stringify(obj))
const result = new URLSearchParams(removeUndefined).toString();
return result ? `?${result}`: '';
}
console.log(urlParams({qwe: undefined, txt: 'asd'})) // '?txt=asd'
console.log(urlParams({qwe: undefined})) // ''
Upvotes: 1
Reputation: 21272
The UrlSearchParams
API is a great suggestion, but I can't believe nobody mentioned the incredibly useful .get
and .set
methods. They can be used to manipulate the query string and not only they're very easy to use, they also solve a number of issues you might encounter. For example, in my case I wanted to build a query string without duplicate keys. .set
solves this problem for you. Quoting from the MDN docs:
URLSearchParams.set() Sets the value associated with a given search parameter to the given value. If there are several values, the others are deleted.
Example (from MDN):
let url = new URL('https://example.com?foo=1&bar=2');
let params = new URLSearchParams(url.search);
// Add a third parameter
params.set('baz', 3);
params.toString(); // "foo=1&bar=2&baz=3"
Alternative, shorter syntax:
let url = new URL('https://example.com?foo=1&bar=2');
// Add a third parameter
url.searchParams.set('baz', 3);
url.searchParams.toString(); // "foo=1&bar=2&baz=3"
Upvotes: 5
Reputation: 626
Create an URL
object and append the values to seachParameters
let stringUrl = "http://www.google.com/search";
let url = new URL(stringUrl);
let params = url.searchParams;
params.append("q", "This is seach query");
console.log(url.toString());
The output will be
http://www.google.com/search?q=This+is+seach+query
Upvotes: 39
Reputation: 9689
If you're using jQuery you might want to check out jQuery.param()
http://api.jquery.com/jQuery.param/
Example:
var params = {
parameter1: 'value1',
parameter2: 'value2',
parameter3: 'value3'
};
var query = $.param(params);
console.log(query);
This will print out:
parameter1=value1¶meter2=value2¶meter3=value3
Upvotes: 148
Reputation: 1441
Might be a bit redundant but the cleanest way i found which builds on some of the answers here:
const params: {
key1: 'value1',
key2: 'value2',
key3: 'value3',
}
const esc = encodeURIComponent;
const query = Object.keys(params)
.map(k => esc(k) + '=' + esc(params[k]))
.join('&');
return fetch('my-url', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: query,
})
Upvotes: 5
Reputation: 546
I know this is very late answer but works very well...
var obj = {
a:"a",
b:"b"
}
Object.entries(obj).map(([key, val])=>`${key}=${val}`).join("&");
note: object.entries will return key,values pairs
output from above line will be a=a&b=b
Hope its helps someone.
Happy Coding...
Upvotes: 3
Reputation: 4458
The URLSearchParams API is available in all modern browsers. For example:
const params = new URLSearchParams({
var1: "value",
var2: "value2",
arr: "foo",
});
console.log(params.toString());
//Prints "var1=value&var2=value2&arr=foo"
Upvotes: 418
Reputation: 13673
2k20 update: use Josh's solution with URLSearchParams.toString().
Old answer:
Without jQuery
var params = {
parameter1: 'value_1',
parameter2: 'value 2',
parameter3: 'value&3'
};
var esc = encodeURIComponent;
var query = Object.keys(params)
.map(k => esc(k) + '=' + esc(params[k]))
.join('&');
For browsers that don't support arrow function syntax which requires ES5, change the .map...
line to
.map(function(k) {return esc(k) + '=' + esc(params[k]);})
Upvotes: 261
Reputation: 18803
var params = { width:1680, height:1050 };
var str = jQuery.param( params );
console.log(str)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Upvotes: 0
Reputation: 18975
These answers are very helpful, but i want to add another answer, that may help you build full URL.
This can help you concat base url
, path
, hash
and parameters
.
var url = buildUrl('http://mywebsite.com', {
path: 'about',
hash: 'contact',
queryParams: {
'var1': 'value',
'var2': 'value2',
'arr[]' : 'foo'
}
});
console.log(url);
You can download via npm https://www.npmjs.com/package/build-url
Demo:
;(function () {
'use strict';
var root = this;
var previousBuildUrl = root.buildUrl;
var buildUrl = function (url, options) {
var queryString = [];
var key;
var builtUrl;
var caseChange;
// 'lowerCase' parameter default = false,
if (options && options.lowerCase) {
caseChange = !!options.lowerCase;
} else {
caseChange = false;
}
if (url === null) {
builtUrl = '';
} else if (typeof(url) === 'object') {
builtUrl = '';
options = url;
} else {
builtUrl = url;
}
if(builtUrl && builtUrl[builtUrl.length - 1] === '/') {
builtUrl = builtUrl.slice(0, -1);
}
if (options) {
if (options.path) {
var localVar = String(options.path).trim();
if (caseChange) {
localVar = localVar.toLowerCase();
}
if (localVar.indexOf('/') === 0) {
builtUrl += localVar;
} else {
builtUrl += '/' + localVar;
}
}
if (options.queryParams) {
for (key in options.queryParams) {
if (options.queryParams.hasOwnProperty(key) && options.queryParams[key] !== void 0) {
var encodedParam;
if (options.disableCSV && Array.isArray(options.queryParams[key]) && options.queryParams[key].length) {
for(var i = 0; i < options.queryParams[key].length; i++) {
encodedParam = encodeURIComponent(String(options.queryParams[key][i]).trim());
queryString.push(key + '=' + encodedParam);
}
} else {
if (caseChange) {
encodedParam = encodeURIComponent(String(options.queryParams[key]).trim().toLowerCase());
}
else {
encodedParam = encodeURIComponent(String(options.queryParams[key]).trim());
}
queryString.push(key + '=' + encodedParam);
}
}
}
builtUrl += '?' + queryString.join('&');
}
if (options.hash) {
if(caseChange)
builtUrl += '#' + String(options.hash).trim().toLowerCase();
else
builtUrl += '#' + String(options.hash).trim();
}
}
return builtUrl;
};
buildUrl.noConflict = function () {
root.buildUrl = previousBuildUrl;
return buildUrl;
};
if (typeof(exports) !== 'undefined') {
if (typeof(module) !== 'undefined' && module.exports) {
exports = module.exports = buildUrl;
}
exports.buildUrl = buildUrl;
} else {
root.buildUrl = buildUrl;
}
}).call(this);
var url = buildUrl('http://mywebsite.com', {
path: 'about',
hash: 'contact',
queryParams: {
'var1': 'value',
'var2': 'value2',
'arr[]' : 'foo'
}
});
console.log(url);
Upvotes: 0
Reputation: 1614
You can do that nowadays with FormData
and URLSearchParams
without the need to loop over anything.
const formData = new FormData(form);
const searchParams = new URLSearchParams(formData);
const queryString = searchParams.toString();
Older browsers will need a polyfill, though.
Upvotes: 5
Reputation: 3975
Making use of Object.entries()
, which returns an array of object's [key, value]
pairs. For example, for {a: 1, b: 2}
it would return [['a', 1], ['b', 2]]
. It is not supported (and won't be) only by IE.
const buildURLQuery = obj =>
Object.entries(obj)
.map(pair => pair.map(encodeURIComponent).join('='))
.join('&');
buildURLQuery({name: 'John', gender: 'male'});
"name=John&gender=male"
Upvotes: 22
Reputation: 1003
querystring can help.
So, you can
const querystring = require('querystring')
url += '?' + querystring.stringify(parameters)
Upvotes: 14
Reputation: 35341
This doesn't directly answer your question, but here's a generic function which will create a URL that contains query string parameters. The parameters (names and values) are safely escaped for inclusion in a URL.
function buildUrl(url, parameters){
var qs = "";
for(var key in parameters) {
var value = parameters[key];
qs += encodeURIComponent(key) + "=" + encodeURIComponent(value) + "&";
}
if (qs.length > 0){
qs = qs.substring(0, qs.length-1); //chop off last "&"
url = url + "?" + qs;
}
return url;
}
// example:
var url = "http://example.com/";
var parameters = {
name: "George Washington",
dob: "17320222"
};
console.log(buildUrl(url, parameters));
// => http://www.example.com/?name=George%20Washington&dob=17320222
Upvotes: 59
Reputation: 76
Is is probably too late to answer your question.
I had the same question and I didn't like to keep appending strings to create a URL. So, I started using $.param as techhouse explained.
I also found a URI.js library that creates the URLs easily for you. There are several examples that will help you: URI.js Documentation.
Here is one of them:
var uri = new URI("?hello=world");
uri.setSearch("hello", "mars"); // returns the URI instance for chaining
// uri == "?hello=mars"
uri.setSearch({ foo: "bar", goodbye : ["world", "mars"] });
// uri == "?hello=mars&foo=bar&goodbye=world&goodbye=mars"
uri.setSearch("goodbye", "sun");
// uri == "?hello=mars&foo=bar&goodbye=sun"
// CAUTION: beware of arrays, the following are not quite the same
// If you're dealing with PHP, you probably want the latter…
uri.setSearch("foo", ["bar", "baz"]);
uri.setSearch("foo[]", ["bar", "baz"]);`
Upvotes: 1
Reputation: 8873
You don't actually need a form to do this with Prototype. Just use Object.toQueryString function:
Object.toQueryString({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })
// -> 'action=ship&order_id=123&fees=f1&fees=f2&label=a%20demo'
Upvotes: 1
Reputation: 6178
With jQuery you can do this by $.param
$.param({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })
// -> "action=ship&order_id=123&fees%5B%5D=f1&fees%5B%5D=f2&label=a+demo"
Upvotes: 22
Reputation: 349
For those of us who prefer jQuery, you would use the form plugin: http://plugins.jquery.com/project/form, which contains a formSerialize method.
Upvotes: 2
Reputation: 123463
If you don't want to use a library, this should cover most/all of the same form element types.
function serialize(form) {
if (!form || !form.elements) return;
var serial = [], i, j, first;
var add = function (name, value) {
serial.push(encodeURIComponent(name) + '=' + encodeURIComponent(value));
}
var elems = form.elements;
for (i = 0; i < elems.length; i += 1, first = false) {
if (elems[i].name.length > 0) { /* don't include unnamed elements */
switch (elems[i].type) {
case 'select-one': first = true;
case 'select-multiple':
for (j = 0; j < elems[i].options.length; j += 1)
if (elems[i].options[j].selected) {
add(elems[i].name, elems[i].options[j].value);
if (first) break; /* stop searching for select-one */
}
break;
case 'checkbox':
case 'radio': if (!elems[i].checked) break; /* else continue */
default: add(elems[i].name, elems[i].value); break;
}
}
}
return serial.join('&');
}
Upvotes: 7
Reputation: 5787
As Stein says, you can use the prototype javascript library from http://www.prototypejs.org.
Include the JS and it is very simple then, $('formName').serialize()
will return what you want!
Upvotes: 2
Reputation: 5119
No, I don't think standard JavaScript has that built in, but Prototype JS has that function (surely most other JS frameworks have too, but I don't know them), they call it serialize.
I can reccomend Prototype JS, it works quite okay. The only drawback I've really noticed it it's size (a few hundred kb) and scope (lots of code for ajax, dom, etc.). Thus if you only want a form serializer it's overkill, and strictly speaking if you only want it's Ajax functionality (wich is mainly what I used it for) it's overkill. Unless you're careful you may find that it does a little too much "magic" (like extending every dom element it touches with Prototype JS functions just to find elements) making it slow on extreme cases.
Upvotes: 10
Reputation: 57354
I'm not entirely certain myself, I recall seeing jQuery did it to an extent, but it doesn't handle hierarchical records at all, let alone in a php friendly way.
One thing I do know for certain, is when building URLs and sticking the product into the dom, don't just use string-glue to do it, or you'll be opening yourself to a handy page breaker.
For instance, certain advertising software in-lines the version string from whatever runs your flash. This is fine when its adobes generic simple string, but however, that's very naive, and blows up in an embarrasing mess for people whom have installed Gnash, as gnash'es version string happens to contain a full blown GPL copyright licences, complete with URLs and <a href> tags. Using this in your string-glue advertiser generator, results in the page blowing open and having imbalanced HTML turning up in the dom.
The moral of the story:
var foo = document.createElement("elementnamehere");
foo.attribute = allUserSpecifiedDataConsideredDangerousHere;
somenode.appendChild(foo);
Not:
document.write("<elementnamehere attribute=\""
+ ilovebrokenwebsites
+ "\">"
+ stringdata
+ "</elementnamehere>");
Google need to learn this trick. I tried to report the problem, they appear not to care.
Upvotes: 3