Window.open y pasar parámetros por método de publicación

97

Con el método window.open abro un nuevo sitio con parámetros, que tengo que pasar por método de publicación. Encontré una solución, pero desafortunadamente no funciona. Este es mi codigo:

<script  type="text/javascript">    
function openWindowWithPost(url,name,keys,values)
{
    var newWindow = window.open(url, name);

    if (!newWindow) return false;

    var html = "";
    html += "<html><head></head><body><form id='formid' method='post' action='" + url +"'>";

    if (keys && values && (keys.length == values.length))
        for (var i=0; i < keys.length; i++)
            html += "<input type='hidden' name='" + keys[i] + "' value='" + values[i] + "'/>";

    html += "</form><script type='text/javascript'>document.getElementById(\"formid\").submit()</sc"+"ript></body></html>";

    newWindow.document.write(html);
    return newWindow;
}
</script>  

A continuación, creo matrices:

<script type="text/javascript">    
var values= new Array("value1", "value2", "value3") 
var keys= new Array("a","b","c") 
</script>  

Y llamar a la función por:

<input id="Button1" type="button" value="Pass values" onclick="openWindowWithPost('test.asp','',keys,values)" />   

Pero, cuando hago clic en este botón, el sitio test.asp está vacío (por supuesto, intento obtener valores de paso - Request.Form("b")).

¿Cómo podría resolver este problema, por qué no puedo obtener valores de paso?

luk4443
fuente
2
¿Qué no funciona? Guardé una copia en jsfiddle.net/TZMMF y funciona como se esperaba.
PleaseStand
Gracias por responder. Sí, lo siento, el código anterior funciona. Pero pruebo esta función con una matriz de claves: <script type = "text / javascript"> var values ​​= new Array ("value1", "value2", "value3") var keys = new Array ("1", "2 "," 3 ") // en lugar de a, b, c </script> obtengo valor por Request.Form (" 2 ") En IE y Firefox obtengo una página vacía.
luk4443

Respuestas:

121

En lugar de escribir un formulario en la nueva ventana (que es complicado de corregir, con la codificación de valores en el código HTML), simplemente abra una ventana vacía y publique un formulario en ella.

Ejemplo:

<form id="TheForm" method="post" action="test.asp" target="TheWindow">
<input type="hidden" name="something" value="something" />
<input type="hidden" name="more" value="something" />
<input type="hidden" name="other" value="something" />
</form>

<script type="text/javascript">
window.open('', 'TheWindow');
document.getElementById('TheForm').submit();
</script>

Editar:

Para establecer los valores en el formulario de forma dinámica, puede hacer lo siguiente:

function openWindowWithPost(something, additional, misc) {
  var f = document.getElementById('TheForm');
  f.something.value = something;
  f.more.value = additional;
  f.other.value = misc;
  window.open('', 'TheWindow');
  f.submit();
}

Para publicar el formulario, llama a la función con los valores, como openWindowWithPost('a','b','c');.

Nota: Varié los nombres de los parámetros en relación con los nombres de los formularios para mostrar que no tienen que ser iguales. Por lo general, los mantendría similares entre sí para facilitar el seguimiento de los valores.

Guffa
fuente
Eso es exactamente lo que estaba pensando. Sin embargo, el código original publicado parecía funcionar ... excepto en IE.
PleaseStand
Gracias por responder. Pero tengo una tabla, donde en la columna hay botones. Cuando hago clic en este botón, abro una nueva página y paso algunos parámetros. Entonces tengo que escribir la función, y para cada botón llamarla y pasar argumentos fijos. Mi pregunta, ¿cómo podría reescribir su código anterior para que funcione?
luk4443
1
@ luk4443: Si usa la URL cuando abre la ventana, la página será reemplazada cuando publique el formulario. Coloque la URL en la actionpropiedad del formulario.
Guffa
1
@Guffa alguna forma de simular también el comportamiento de target="_blank"?
Everton
2
@EvertonAgner: Use un nombre único para la ventana y funcionará como _blank.
Guffa
62

Como quería todo el formulario dentro del javascript, en lugar de escribirlo en etiquetas, puede hacer esto:

var form = document.createElement("form");
form.setAttribute("method", "post");
form.setAttribute("action", "openData.do");

form.setAttribute("target", "view");

var hiddenField = document.createElement("input"); 
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", "message");
hiddenField.setAttribute("value", "val");
form.appendChild(hiddenField);
document.body.appendChild(form);

window.open('', 'view');

form.submit();
Mercenario
fuente
5
Sin implementación basada en jQuery y Pure JavaScript. Gracias.
Pawan Pillai
2
La página de @Mercenary está abierta en una nueva pestaña aquí, ¿puedo abrir la página en una nueva ventana emergente?
Yaje
29

Aunque llego 3 años tarde, pero para simplificar el ejemplo de Guffa, ni siquiera necesitas tener el formulario en la página:

$('<form method="post" action="test.asp" target="TheWindow">
       <input type="hidden" name="something" value="something">
       ...
   </form>').submit();

Editado:

$('<form method="post" action="test.asp" target="TheWindow">
       <input type="hidden" name="something" value="something">
       ...
   </form>').appendTo('body').submit().remove();

Quizás un consejo útil para alguien :)

Andrius Naruševičius
fuente
7
Esta solución está incompleta. Primero debe agregar este formulario al cuerpo y luego enviarlo. Entonces, donde dice .submit (); debería decir .appendTo ('cuerpo'). submit ();
Jonathan van de Veen
1
Sin esta parte $("body").append(form);no funcionará
Axel
4
Si agrega un .remove()después de lo sugerido por Jonathan .appendTo('body').submit(), incluso limpiará después de usted mismo y no abarrotará la página actual con objetos de formulario.
Simon
24

Estoy completamente de acuerdo con la respuesta de mercenario publicada anteriormente y creé esta función para mí que funciona para mí. No es una respuesta, es un comentario en la publicación anterior de un mercenario.

function openWindowWithPostRequest() {
  var winName='MyWindow';
  var winURL='search.action';
  var windowoption='resizable=yes,height=600,width=800,location=0,menubar=0,scrollbars=1';
  var params = { 'param1' : '1','param2' :'2'};         
  var form = document.createElement("form");
  form.setAttribute("method", "post");
  form.setAttribute("action", winURL);
  form.setAttribute("target",winName);  
  for (var i in params) {
    if (params.hasOwnProperty(i)) {
      var input = document.createElement('input');
      input.type = 'hidden';
      input.name = i;
      input.value = params[i];
      form.appendChild(input);
    }
  }              
  document.body.appendChild(form);                       
  window.open('', winName,windowoption);
  form.target = winName;
  form.submit();                 
  document.body.removeChild(form);           
}
Youdhveer
fuente
12

Simplemente puede usar target="_blank"en el formulario.

<form action="action.php" method="post" target="_blank">
    <input type="hidden" name="something" value="some value">
</form>

Agregue entradas ocultas de la manera que prefiera y luego simplemente envíe el formulario con JS.

Muelle
fuente
Además, ya window.openque se bloquearía como una ventana emergente, cuando no se llama dentro de un clickcontrolador (o cualquier evento disparado por el usuario como ese)
Xenos
4

Creé una función para generar un formulario, basado en la URL, el destino y un objeto como el método POST/ GETdata y submit. Admite tipos anidados y mixtos dentro de ese objeto, por lo que puede replicar completamente cualquier estructura que lo alimente: PHP lo analiza automáticamente y lo devuelve como una matriz anidada. Sin embargo, hay una única restricción: los corchetes [y ]no deben ser parte de ninguna clave en el objeto (como {"this [key] is problematic" : "hello world"}). Si alguien sabe cómo escapar correctamente, ¡dígalo!

Sin más preámbulos, aquí está la fuente:

Ejemplo de uso:

document.body.onclick = function() {
  var obj = {
    "a": [1, 2, [3, 4]],
    "b": "a",
    "c": {
      "x": [1],
      "y": [2, 3],
      "z": [{
        "a": "Hello",
        "b": "World"
      }, {
        "a": "Hallo",
        "b": "Welt"
      }]
    }
  };

  var form = getForm("http://example.com", "_blank", obj, "post");

  document.body.appendChild(form);
  form.submit();
  form.parentNode.removeChild(form);
}

Ceremonia
fuente
Vaya, la URL en el ejemplo de uso estaba mal formada. si lo arregla, no hay más errores.
Ceremonia
1
Todavía parece roto, tengo una página en blanco.
Adam Parkin
2

Encontré una mejor manera de pasar parámetros a la ventana emergente e incluso recuperar parámetros de ella:

En la pagina principal:

var popupwindow;
var sharedObject = {};

function openPopupWindow()
{
   // Define the datas you want to pass
   sharedObject.var1 = 
   sharedObject.var2 = 
   ...

   // Open the popup window
   window.open(URL_OF_POPUP_WINDOW, NAME_OF_POPUP_WINDOW, POPUP_WINDOW_STYLE_PROPERTIES);
   if (window.focus) { popupwindow.focus(); }
}

function closePopupWindow()
{
    popupwindow.close();

    // Retrieve the datas from the popup window
    = sharedObject.var1;
    = sharedObject.var2;
    ...
}

En la ventana emergente:

var sharedObject = window.opener.sharedObject;

// function you have to to call to close the popup window
function myclose()
{
    //Define the parameters you want to pass to the main calling window
    sharedObject.var1 = 
    sharedObject.var2 = 
    ...
    window.opener.closePopupWindow();
}

Eso es !

Y esto es muy conveniente porque:

  • No tiene que establecer parámetros en la URL de la ventana emergente.
  • Sin forma para definir
  • Puede utilizar parámetros ilimitados incluso objetos.
  • Bidireccional: puede pasar parámetros Y, si lo desea, puede recuperar nuevos parámetros.
  • Muy fácil de implementar.

¡Que te diviertas!

Hombre azul
fuente
nota: window.openerno es compatible con todos los navegadores.
Raptor
1

Quería hacer esto en React usando Js simples y fetch polyfill . OP no dijo que quería específicamente crear un formulario e invocar el método de envío en él, así que lo hice publicando los valores del formulario como json:

examplePostData = {
    method: 'POST',
    headers: {
       'Content-type' : 'application/json',
       'Accept' : 'text/html'
    },
    body: JSON.stringify({
        someList: [1,2,3,4],
        someProperty: 'something',
        someObject: {some: 'object'}
    })
}

asyncPostPopup = () => {

    //open a new window and set some text until the fetch completes
    let win=window.open('about:blank')
    writeToWindow(win,'Loading...')

    //async load the data into the window
    fetch('../postUrl', this.examplePostData)
    .then((response) => response.text())
    .then((text) => writeToWindow(win,text))
    .catch((error) => console.log(error))
}

writeToWindow = (win,text) => {
    win.document.open()
    win.document.write(text)
    win.document.close()
}

fuente
0

La acción de envío predeterminada es Ext.form.action.Submit, que utiliza una solicitud Ajax para enviar los valores del formulario a una URL configurada. Para habilitar el envío normal del navegador de un formulario externo, use la opción de configuración estándar de envío.

Enlace: http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.form.Basic-cfg-standardSubmit

solución: ponga standardSubmit: true en su configuración. Espero que esto te ayude :)

usuario2420964
fuente
0

He usado esto en el pasado, ya que normalmente usamos la sintaxis razor para codificar

@using (Html.BeginForm("actionName", "controllerName", FormMethod.Post, new { target = "_blank" }))

{

// agregar formulario oculto y archivado aquí

}

rescates
fuente