Cómo construir una cadena de consulta con Javascript

Respuestas:

-24

Intenté buscar una respuesta a esta pregunta hace algún tiempo, pero terminé escribiendo mi propia función que extrae los valores del formulario.

No es perfecto pero se ajusta a mis necesidades.

function form_params( form )
{
    var params = new Array()
    var length = form.elements.length
    for( var i = 0; i < length; i++ )
    {
        element = form.elements[i]

        if(element.tagName == 'TEXTAREA' )
        {
            params[element.name] = element.value
        }
        else if( element.tagName == 'INPUT' )
        {
            if( element.type == 'text' || element.type == 'hidden' || element.type == 'password')
            {
                params[element.name] = element.value
            }
            else if( element.type == 'radio' && element.checked )
            {
                if( !element.value )
                    params[element.name] = "on"
                else
                    params[element.name] = element.value

            }
            else if( element.type == 'checkbox' && element.checked )
            {
                if( !element.value )
                    params[element.name] = "on"
                else
                    params[element.name] = element.value
            }
        }
    }
    return params;
}

form_params devuelve una asignación (clave -> valor) de los parámetros. la entrada es el elemento de formulario (elemento DOM)

No maneja campos que permiten la selección múltiple.

Hasen
fuente
44
¿Soy solo yo o esto no responde a la pregunta? Estaba pidiendo una cadena de consulta, no una matriz asignada.
Jake Wilson
2
@JakeWilson Sí, esta respuesta solo responde la mitad de la pregunta. La matriz aún necesita entrar en un formato de cadena de consulta.
Hutch Moore
8
wow, debo haber sido un novato en JS en ese entonces. Utilizando new Array()para inicializar un diccionario. Pero, de nuevo, ¡el código se ve mucho más limpio que algunas de las tonterías que escribiría en estos días!
hasen
2
Quizás tengas en cuenta la posibilidad de editar esta respuesta o, bueno, ¿eliminarla? Tiene cada vez más votos negativos cada vez que me desplazo hacia ella = -D (incluso recuerdo el momento en que tenía una relación positiva ...)
Klesun
1
@ArturKlesun sí, no. No me importa Puede intentar pedirle a la persona que hizo la pregunta que no acepte esta respuesta.
Hasen
220

Actualización 2k20: use la solución de Josh con URLSearchParams.toString () .

Vieja respuesta:


Sin 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('&');

Para los navegadores que no admiten la sintaxis de la función de flecha que requiere ES5, cambie la .map...línea a

    .map(function(k) {return esc(k) + '=' + esc(params[k]);})
Klesun
fuente
8
La mejor solución que he visto hasta ahora: muy limpia y concisa. Sin embargo, hay un par de advertencias. 1) en .map (), tanto k como params [k] deben codificarse, por ejemplo encodeURIComponent (k) y encodeURIComponent (params [k]). 2) Se le permite tener más de una instancia de un parámetro con nombre en una cadena de consulta. Si desea esa capacidad, tendrá que usar una matriz en lugar de un objeto (la mayoría de las aplicaciones no querrán o necesitarán eso).
John Deighan
9
3) No todos los navegadores admitirán la sintaxis de la función de flecha (que requiere ES5). Si desea admitir todos los navegadores (y codificar las partes), reemplace el .map () anterior con .map (function (k) {return encodeURIComponent (k) + '=' + encodeURIComponent (params [k]);})
John Deighan
1
Hermoso. Verdaderamente hermoso.
Mikko Ohtamaa
9
"No es suficiente jquery"
Eugene Pankov
1
@ user1738579 Edité la respuesta para incluir también su ejemplo para no ES5.
Taylor Edmiston
134

Si está utilizando jQuery, puede consultar jQuery.param() http://api.jquery.com/jQuery.param/

Ejemplo:

var params = {
    parameter1: 'value1',
    parameter2: 'value2',
    parameter3: 'value3' 
};
var query = $.param(params);
document.write(query);
Klemen Tušar
fuente
13
¡Esta es realmente la respuesta correcta! La cadena de consulta para un formulario es $.param($('#myform').serializeArray()).
Jesse
77
@Jesse, ese sería el mismo resultado que:$('#myform').serialize()
cuchilla
94
jQuery !== JavaScript
gphilip
14
@gphilip Bueno, por eso comencé la respuesta con "Si estás usando jQuery ...". De lo contrario, si desea implementarlo en vanilla JS, puede examinar la implementación jQuery.param()aquí github.com/jquery/jquery/blob/master/src/serialize.js :)
Klemen Tušar
2
A diferencia de mi respuesta, esta admite objetos anidados comosomeStr=value1&someObj[a]=5&someObj[b]=6&someArr[]=1&someArr[]=2
Klesun
113

La API URLSearchParams está disponible en todos los navegadores modernos. Por ejemplo:

const params = new URLSearchParams({
  var1: "value",
  var2: "value2",
  arr: "foo",
});
console.log(params.toString());
//Prints "var1=value&var2=value2&arr=foo"

Josh
fuente
3
La mejor respuesta aquí imo. Solo para agregarlo, puede hacerlo params.append(key, value)más tarde para agregar nuevos parámetros de búsqueda en escenarios más complicados.
Mingwei Zhang
44
Tenga en cuenta que los valores indefinidos y nulos se incluyen en la cadena final:x=null&y=undefined
pomber
2
Además, si ya tiene un objeto URL (por ejemplo const url = new URL("https://stackoverflow.com")), puede configurar sus cadenas de consulta url.search = new URLSearchParams({foo: "bar"})ourl.searchParams.append("foo", "bar")
Miguel Pynto
Tenga en cuenta que TS advertirá sobre el uso de un objeto simple, pero no obstante funciona bien
Vadorequest
@pomber ¿Alguna buena idea para filtrar esos elementos indefinidos?
Dan Gayle
53

Esto no responde directamente a su pregunta, pero aquí hay una función genérica que creará una URL que contiene parámetros de cadena de consulta. Los parámetros (nombres y valores) se escapan de forma segura para su inclusión en una 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
Miguel
fuente
1
¿Hay alguna función incorporada similar a esta en uno de los marcos javascript populares como jquery, mootools, etc.?
Samuel
Una solución JavaScript nativa más sólida está en stackoverflow.com/a/1714899/1269037
Dan Dascalescu
La implementación más extraña de la historia, ¿por qué necesita inicializar un new Arraytiempo mientras realmente la usa como un objeto? o, O
Umut Sirin
@UmutSirin Lol, sí, no sabía mucho sobre Javascript en ese momento. xD Creo que lo estaba tratando como una matriz PHP. Siéntase libre de refactorizar si lo desea.
Michael
@ Michael Jaja, sí. Acabo de enviar una edición. ¡Gracias por la respuesta!
Umut Sirin
22

Con jQuery puedes hacer esto $.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"
manish_s
fuente
17

ES2017 (ES8)

Haciendo uso de Object.entries(), que devuelve una matriz de [key, value]pares de objetos . Por ejemplo, porque {a: 1, b: 2}volvería [['a', 1], ['b', 2]]. No es compatible (y no será) solo por IE.

Código:

const buildURLQuery = obj =>
      Object.entries(obj)
            .map(pair => pair.map(encodeURIComponent).join('='))
            .join('&');

Ejemplo:

buildURLQuery({name: 'John', gender: 'male'});

Resultado:

"name=John&gender=male"
Przemek
fuente
Haga uso de url.spec.whatwg.org/#urlsearchparams en su lugar
Boris
10

No, no creo que JavaScript estándar tenga eso incorporado, pero Prototype JS tiene esa función (seguramente la mayoría de los otros frameworks JS también lo tienen, pero no los conozco), lo llaman serializar .

Puedo recomendar Prototype JS, funciona bastante bien. El único inconveniente que realmente he notado es su tamaño (unos pocos cientos de kb) y su alcance (mucho código para ajax, dom, etc.). Por lo tanto, si solo desea un serializador de formularios, es excesivo, y estrictamente hablando, si solo desea su funcionalidad Ajax (que es principalmente para lo que lo usé), es excesivo. A menos que tenga cuidado, puede encontrar que hace demasiado "magia" (como extender cada elemento dom que toca con las funciones de Prototype JS solo para encontrar elementos), lo que lo hace lento en casos extremos.

Stein G. Strindhaug
fuente
Solo me pregunto si hay algo incorporado. Parece que debería haberlo. Odio el prototipo, pero no estoy sosteniendo eso contra ti :)
Cuando se diseñó JavaScript, todavía no se descubrió Ajax, por lo tanto, analizar un formulario solo para obtener la cadena de consulta (que se crearía cuando se enviara) probablemente no tenía mucho sentido. Hoy lo hace, difícil ... Por cierto, en comparación con script.aculo.us, el prototipo es bueno . :)
Stein G. Strindhaug el
10

querystring puede ayudar.

Así que puedes

const querystring = require('querystring')

url += '?' + querystring.stringify(parameters)
ImLeo
fuente
3
Para aplicaciones frontend también puede considerar npmjs.com/package/qs
Robert Pankowecki
@RobertPankowecki, sí, qs es mejor y ya está en mi arsenal, ¡salud!
ImLeo
6

Si no desea utilizar una biblioteca, esto debería cubrir la mayoría / todos los mismos tipos de elementos de formulario.

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('&');
}
Jonathan Lonowski
fuente
¡Gracias! Estaba enfrentando el mismo problema que el póster original, y su función era exactamente lo que necesitaba.
dagw 03 de
4

En realidad, no necesita un formulario para hacer esto con Prototype. Simplemente use la función Object.toQueryString :

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'
Thibaut Barrère
fuente
44
De acuerdo, respondiste hace casi 10 años, pero este código ahora está en desuso.
SEOF
4

Puede hacer eso hoy en día con FormDatay URLSearchParamssin la necesidad de repetir nada.

const formData = new FormData(form);
const searchParams = new URLSearchParams(formData);
const queryString = searchParams.toString();

Sin embargo, los navegadores más antiguos necesitarán un polyfill.

Björn Tantau
fuente
3

No estoy del todo seguro, recuerdo haber visto que jQuery lo hizo hasta cierto punto, pero no maneja los registros jerárquicos en absoluto, y mucho menos de una manera amigable con php.

Una cosa que sí sé con certeza es que al crear URL y pegar el producto en el dom, no solo use string-glue para hacerlo, o se abrirá a un práctico separador de páginas.

Por ejemplo, cierto software de publicidad integra la cadena de versión de lo que sea que ejecute su flash. Esto está bien cuando se trata de una cadena simple genérica de adobes, pero sin embargo, eso es muy ingenuo y explota en un lío vergonzoso para las personas que han instalado Gnash, ya que la cadena de versión de gnash contiene una licencia de copyright GPL completa, completa con URL y etiquetas <a href>. Al usar esto en el generador de anunciantes de pegamento de cadenas, se abre la página y aparece un HTML desequilibrado en el dom.

La moraleja de la historia:

   var foo = document.createElement("elementnamehere"); 
   foo.attribute = allUserSpecifiedDataConsideredDangerousHere; 
   somenode.appendChild(foo); 

No:

   document.write("<elementnamehere attribute=\"" 
        + ilovebrokenwebsites 
        + "\">" 
        + stringdata 
        + "</elementnamehere>");

Google necesita aprender este truco. Traté de informar el problema, parece que no les importa.

Kent Fredric
fuente
Tocar el asunto exacto. Document.write es tan 1995, de todos modos.
2

Como dice Stein, puede utilizar la biblioteca prototipo de JavaScript de http://www.prototypejs.org . Incluya el JS y es muy simple, ¡ $('formName').serialize()le devolverá lo que desea!

Shyam
fuente
2

Puede ser un poco redundante, pero la forma más limpia que encontré se basa en algunas de las respuestas aquí:

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,
})

Fuente

David Pascoal
fuente
1

Estas respuestas son muy útiles, pero quiero agregar otra respuesta, que puede ayudarlo a construir una URL completa. Esto le puede ayudar a concat de base url, path, hashy parameters.

var url = buildUrl('http://mywebsite.com', {
        path: 'about',
        hash: 'contact',
        queryParams: {
            'var1': 'value',
            'var2': 'value2',
            'arr[]' : 'foo'
        }
    });
    console.log(url);

Puede descargar a través de npm https://www.npmjs.com/package/build-url

Manifestación:

;(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);

Hien Nguyen
fuente
1

Sé que esta es una respuesta muy tardía pero funciona muy bien ...

var obj = {
a:"a",
b:"b"
}

Object.entries(obj).map(([key, val])=>`${key}=${val}`).join("&");

nota: object.entries devolverá clave, pares de valores

la salida de la línea anterior será a = a & b = b

Espero que ayude a alguien.

Feliz codificación ...

ajaykumar mp
fuente
0

Probablemente sea demasiado tarde para responder a su pregunta.
Tenía la misma pregunta y no me gustaba seguir agregando cadenas para crear una URL. Entonces, comencé a usar $ .param como explicó Techhouse .
También encontré una biblioteca URI.js que crea las URL fácilmente para usted. Hay varios ejemplos que le ayudarán a: URI.js Documentación .
Aqui esta uno de ellos:

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"]);`
SaraNa
fuente
0

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>

Bashirpour
fuente