Como enviar um formulário HTML sem redirecionamento

95

Se eu tiver um formulário como este,

<form action="/Car/Edit/17" id="myForm" method="post" name="myForm"> ... </form>

como posso enviá-lo sem redirecionar para outra visualização por JavaScript / jQuery?

Eu li muitas respostas de Stack Overflow, mas todas elas me redirecionam para a visualização retornada pela função POST.

Duke Nuke
fonte
Você deseja uma solicitação XHR (AJAX)
Sterling Archer de
2
XHR / AJAX é uma maneira - ele envia a postagem e obtém a resposta nos bastidores, para que o navegador nunca saia da página em que está. Outra maneira é um redirecionamento do lado do servidor após o processamento da postagem, o que depende de qual tecnologia de servidor você está usando.
Stephen P
@StephenP Eu uso ASP.NET MVC 5.1.
Duke Nuke de
@Duke, tudo o que estou dizendo é que existe mais de uma abordagem (ajax vs. redirecionamento de servidor) e sua escolha depende de suas necessidades. Os sites modernos provavelmente desejarão fazer ajax. Note também que todas essas respostas estão dizendo que você precisa jQuery - jQuery é ótimo, mas não são , de fato, outras maneiras de fazer ajax ... embora eu seria realmente usar jQuery mim.
Stephen P
1
Meu método é simples, limpo e elegante, e tem apenas 2 linhas de código. Ele não usa scripts e funciona em HTML4 e superior, mesmo se o JavaScript estiver desativado.
Issa Chanzi 01 de

Respostas:

74

Para conseguir o que deseja, você precisa usar jQuery Ajax conforme abaixo:

$('#myForm').submit(function(e){
    e.preventDefault();
    $.ajax({
        url: '/Car/Edit/17/',
        type: 'post',
        data:$('#myForm').serialize(),
        success:function(){
            // Whatever you want to do after the form is successfully submitted
        }
    });
});

Experimente também este:

function SubForm(e){
    e.preventDefault();
    var url = $(this).closest('form').attr('action'),
    data = $(this).closest('form').serialize();
    $.ajax({
        url: url,
        type: 'post',
        data: data,
        success: function(){
           // Whatever you want to do after the form is successfully submitted
       }
   });
}

Solução final

Isso funcionou perfeitamente. Eu chamo essa função deHtml.ActionLink(...)

function SubForm (){
    $.ajax({
        url: '/Person/Edit/@Model.Id/',
        type: 'post',
        data: $('#myForm').serialize(),
        success: function(){
            alert("worked");
        }
    });
}
Amin Jafari
fonte
Funcionou muito bem, o problema é que não quero que seja enviado automaticamente (sempre) dessa forma. Eu gostaria de ter uma função com um nome para fazer essas coisas que você postou na sua resposta. Portanto, posso invocá-lo manualmente quando quiser, para fazê-lo postar o formulário. Como a seguir, posso dar o nome da função a ser invocada. @Html.ActionLink("Add a Report", "Create", "Reports", new { carId = Model.Id }, new { onclick = "FUNCTION_WHICH_SUBMITES_FORM()" })
Duke Nuke de
Isso funcionou:function SubForm (){ alert("1"); //e.preventDefault(); $.ajax({ url:'/Car/Edit/@Model.Id/', type:'post', data:$('#myForm').serialize(), success:function(){ alert("fasf"); } }); }
Duke Nuke de
Por algum motivo, sua segunda solução não funcionou, mas a que postei no último comentário funcionou. Vou adicionar minha solução ao seu post causa só por causa de você que pude conseguir isso.
Duke Nuke
1
o segundo também deve funcionar, pode haver algo diferente, mas se você encontrou a solução, não precisamos seguir por esse caminho agora! que bom que ajudou;)
Amin Jafari
Obrigado, esta resposta também me ajudou a colocar um texto personalizado no lugar do formulário após o envio
Anupam
116

Você pode conseguir isso redirecionando o formulário actionpara um invisível <iframe>. Não requer nenhum JavaScript ou qualquer outro tipo de script.

<iframe name="dummyframe" id="dummyframe" style="display: none;"></iframe>

<form action="submitscript.php" target="dummyframe">
    <!-- Form body here -->
</form>
Issa Chanzi
fonte
1
Isso é ótimo. Mas como posso fazer algo, depois de enviar o formulário? ou seja, os campos de texto do formulário terão que estar vazios, o foco voltará para o primeiro campo, etc.?
Pranjal Choladhara
1
Existe algum tipo de javascript que pode fazer isso. Basta alterar <input type='submit'...para <input type='reset'e adicionaronclick='document.forms["myForm"].submit();'>
Issa Chanzi
Bela resposta! Funciona muito bem
Cybrus de
Tenha cuidado, é provável que recarregue a página em que seu formulário está no iframe, o que pode causar problemas de desempenho se você estiver criando um aplicativo ou um grande site.
Alexandre Daubricourt
22

Coloque um oculto iFramena parte inferior de sua página e targetem seu formulário:

<iframe name="hiddenFrame" width="0" height="0" border="0" style="display: none;"></iframe>

<form action="/Car/Edit/17" id="myForm" method="post" name="myForm" target="hiddenFrame"> ... </form>

Rápido e fácil. Lembre-se de que, embora o targetatributo ainda tenha amplo suporte (e suporte no HTML5), ele foi descontinuado no HTML 4.01.

Portanto, você realmente deve usar o Ajax para se preparar para o futuro.

Steven Black
fonte
De acordo com o MDN, esse comportamento para o targeté totalmente válido, portanto, AJAX ainda é opcional.
Daniel De León
18

Como todas as respostas atuais usam jQuery ou truques com iframe, percebi que não há mal nenhum em adicionar um método apenas com JavaScript:

function formSubmit(event) {
  var url = "/post/url/here";
  var request = new XMLHttpRequest();
  request.open('POST', url, true);
  request.onload = function() { // request successful
  // we can use server response to our request now
    console.log(request.responseText);
  };

  request.onerror = function() {
    // request failed
  };

  request.send(new FormData(event.target)); // create FormData from form that triggered event
  event.preventDefault();
}

// and you can attach form submit event like this for example
function attachFormSubmitEvent(formId){
  document.getElementById(formId).addEventListener("submit", formSubmit);
}
Ethuil UI
fonte
2
Muito obrigado!
Joshua Evans
Eu tiro meu chapéu para você. Passei horas tentando descobrir como fazer com que jquery envie um formulário para um back-end nginx com o parâmetro contentType = false e sempre obter um 415 como resultado. Essa foi a única solução que encontrei que resolveu meu problema específico.
user12066
7

Ok, eu não vou te dizer uma maneira mágica de fazer isso porque não existe. Se você tiver um atributo de ação definido para um elemento de formulário, ele irá redirecionar.

Se você não quiser redirecionar, simplesmente não defina nenhuma ação e defina onsubmit="someFunction();"

No seu someFunction()você faz o que quiser, (com AJAX ou não) e no final, você adiciona return false;para dizer ao navegador para não enviar o formulário ...

Anshu Dwibhashi
fonte
1
Existe uma maneira mágica de fazer isso. Defina um atributo de destino para que o formulário redirecione para algum lugar diferente do quadro atual. Se você adicionar um iframe invisível para coisas como essa em suas páginas. É muito simples.
Issa Chanzi
5

Você precisa do Ajax para fazer isso acontecer. Algo assim:

$(document).ready(function(){
    $("#myform").on('submit', function(){
        var name = $("#name").val();
        var email = $("#email").val();
        var password = $("#password").val();
        var contact = $("#contact").val();

        var dataString = 'name1=' + name + '&email1=' + email + '&password1=' + password + '&contact1=' + contact;
        if(name=='' || email=='' || password=='' || contact=='')
        {
            alert("Please fill in all fields");
        }
        else
        {
            // Ajax code to submit form.
            $.ajax({
                type: "POST",
                url: "ajaxsubmit.php",
                data: dataString,
                cache: false,
                success: function(result){
                    alert(result);
                }
           });
        }
        return false;
    });
});
Bojan Petkovski
fonte
5
Existe algum motivo particular pelo qual você não indenta este código-fonte? Parece um código dos anos 60 antes da invenção do C. Eu pensei que já tínhamos superado isso por muito tempo.
Alfe de
2

Veja a postfunção do jQuery .

Gostaria de criar um botão e definir um onClickListener( $('#button').on('click', function(){});) e enviar os dados na função.

Além disso, veja a preventDefaultfunção de jQuery!

Nagy Vilmos
fonte
2

Solução de uma linha a partir de 2020, se seus dados não devem ser enviados como multipart/form-dataou application/x-www-form-urlencoded:

<form onsubmit='return false'>
    <!-- ... -->           
</form>
Alexandre Daubricourt
fonte
3
Se você combinar isso com os OPs action="...", evita efetivamente a troca de página, mas também evita que os dados sejam enviados pela rede.
Kev
@Kev Eu envio pessoalmente meus dados via JS XHR, por isso não quero redirecionamento de página, pois é um aplicativo JS
Alexandre Daubricourt
@Kev Desculpe, eu deveria ter mencionado isso
Alexandre Daubricourt
1

O efeito desejado também pode ser obtido movendo o botão enviar para fora do formulário, conforme descrito aqui:

Impedir o recarregamento da página e o redirecionamento no formulário submit ajax / jquery

Como isso:

<form id="getPatientsForm">
    Enter URL for patient server
    <br/><br/>
    <input name="forwardToUrl" type="hidden" value="/WEB-INF/jsp/patient/patientList.jsp" />
    <input name="patientRootUrl" size="100"></input>
    <br/><br/>
</form>

<button onclick="javascript:postGetPatientsForm();">Connect to Server</button>
John
fonte
1

Usando este snippet, você pode enviar o formulário e evitar o redirecionamento. Em vez disso, você pode passar a função de sucesso como argumento e fazer o que quiser.

function submitForm(form, successFn){
    if (form.getAttribute("id") != '' || form.getAttribute("id") != null){
        var id = form.getAttribute("id");
    } else {
        console.log("Form id attribute was not set; the form cannot be serialized");
    }

    $.ajax({
        type: form.method,
        url: form.action,
        data: $(id).serializeArray(),
        dataType: "json",
        success: successFn,
        //error: errorFn(data)
    });
}

E então é só fazer:

var formElement = document.getElementById("yourForm");
submitForm(formElement, function() {
    console.log("Form submitted");
});
jmojico
fonte
0

Se você controlar o back-end, use algo como em response.redirectvez de response.send.

Você pode criar páginas HTML personalizadas para isso ou apenas redirecionar para algo que você já possui.

Em Express.js:

const handler = (req, res) => {
  const { body } = req
  handleResponse(body)
  .then(data => {
    console.log(data)
    res.redirect('https://yoursite.com/ok.html')
  })
  .catch(err => {
    console.log(err)
    res.redirect('https://yoursite.com/err.html')
  })
}
...
app.post('/endpoint', handler)
etw3
fonte