Como impedir que os botões enviem formulários

917

Na página seguinte, no Firefox, o botão remover envia o formulário, mas o botão adicionar não. Como evito que o botão remover envie o formulário?

<html>

<head>
    <script type="text/javascript" src="jquery-1.3.2.min.js"></script>
    <script type="text/javascript">
        function addItem() {
            var v = $('form :hidden:last').attr('name');
            var n = /(.*)input/.exec(v);

            var newPrefix;
            if (n[1].length == 0) {
                newPrefix = '1';
            } else {
                newPrefix = parseInt(n[1]) + 1;
            }

            var oldElem = $('form tr:last');
            var newElem = oldElem.clone(true);
            var lastHidden = $('form :hidden:last');

            lastHidden.val(newPrefix);

            var pat = '=\"' + n[1] + 'input';

            newElem.html(newElem.html().replace(new RegExp(pat, 'g'), '=\"' + newPrefix + 'input'));
            newElem.appendTo('table');
            $('form :hidden:last').val('');
        }

        function removeItem() {
            var rows = $('form tr');
            if (rows.length > 2) {
                rows[rows.length - 1].html('');
                $('form :hidden:last').val('');
            } else {
                alert('Cannot remove any more rows');
            }
        }
    </script>
</head>

<body>
    <form autocomplete="off" method="post" action="">
        <p>Title:<input type="text" /></p>
        <button onclick="addItem(); return false;">Add Item</button>
        <button onclick="removeItem(); return false;">Remove Last Item</button>
        <table>
            <th>Name</th>

            <tr>
                <td><input type="text" id="input1" name="input1" /></td>
                <td><input type="hidden" id="input2" name="input2" /></td>
            </tr>
        </table>
        <input id="submit" type="submit" name="submit" value="Submit">
    </form>
</body>

</html>
Khanpo
fonte
qual resposta você recomenda por favor?
Sanepete # 10/18

Respostas:

1798

Você está usando um elemento de botão HTML5. Lembre-se do motivo pelo qual este botão tem um comportamento padrão de envio, conforme declarado na especificação W3, como visto aqui: Botão HTML3 do W3C

Então você precisa especificar seu tipo explicitamente:

<button type="button">Button</button>

para substituir o tipo de envio padrão. Eu só quero apontar a razão pela qual isso acontece =)

=)

Metafaniel
fonte
17
Também quero salientar que um elemento HTML com um atributo type, um dos tipos que é button , não deve ter um tipo padrão de envio . É simplesmente idiota, e um enorme erro nas especificações. Eu uso botões em formulários o tempo todo e, mesmo que fosse um caso de ponta (o que não é), ainda faria sentido que o tipo padrão fosse enviado.
Dudewad 27/10/2015
3
Spent Passei a maior parte desta semana irritado porque meu aplicativo Electron "atualizou" quando abro um modal usando um botão em um formulário. Isso aconteceria uma vez e, em seguida, o aplicativo se comportaria como eu esperava. Eu não tinha absolutamente nenhuma ideia do que estava acontecendo. Era isso! Não tenho nenhum problema com o tipo padrão que está sendo enviado. Parece um pouco difícil, já que levei cinco anos para aprender sobre isso.
freethebees
4
Graças à sua referência, acabei de descobrir que existe um type = reset para o formulário. Impressionante!
Duong Nguyen
602

Defina o tipo nos seus botões:

<button type="button" onclick="addItem(); return false;">Add Item</button>
<button type="button" onclick="removeItem(); return false;">Remove Last Item</button>

... que os impedirão de acionar uma ação de envio quando ocorrer uma exceção no manipulador de eventos. Em seguida, corrija sua removeItem()função para que ela não acione uma exceção:

function removeItem() {
  var rows = $('form tr');
  if ( rows.length > 2 ) {
    // change: work on filtered jQuery object
    rows.filter(":last").html('');
    $('form :hidden:last').val('');
  } else {
    alert('Cannot remove any more rows');
  }
}

Observe a alteração: seu código original extraiu um elemento HTML do conjunto jQuery e tentou chamar um método jQuery - isso gerou uma exceção, resultando no comportamento padrão do botão.

FWIW, há outra maneira de você seguir isso ... Conecte seus manipuladores de eventos usando jQuery e use o método preventDefault () no objeto de evento do jQuery para cancelar o comportamento padrão antecipadamente:

$(function() // execute once the DOM has loaded
{

  // wire up Add Item button click event
  $("#AddItem").click(function(event)
  {
    event.preventDefault(); // cancel default behavior

    //... rest of add logic
  });

  // wire up Remove Last Item button click event
  $("RemoveLastItem").click(function(event)
  {
    event.preventDefault(); // cancel default behavior

    //... rest of remove last logic
  });

});

...

<button type="button" id="AddItem" name="AddItem">Add Item</button>
<button type="button" id="RemoveLastItem" name="RemoveLastItem">Remove Last Item</button>

Essa técnica mantém toda a sua lógica em um único lugar, facilitando a depuração ... também permite implementar um fallback, alterando typeos botões de volta submite manipulando o evento do lado do servidor - isso é conhecido como discreto JavaScript .

Shog9
fonte
4
type = "button" nem sempre funciona no Firefox para mim. Se o js for bastante complicado e houver um erro, o Firefox enviará o formulário de qualquer maneira. Insanidade!
Matthew Bloqueio
1
@MatthewLock: Dificilmente - um erro no script simplesmente desliga esse bloco de código e a ação prossegue como de costume. Tente chamar os métodos de evento jQuery e.preventDefault () e / ou e.stopPropgation () como as primeiras linhas do método. Veja stackoverflow.com/questions/2017755/… para saber mais
brichins
8
type = botão nunca deve enviar o formulário, porém, não importa o que
Matthew Bloqueio
1
return falseé tão importante. às vezes até o usa para o botão enviar ( onclick
Jamie
7
Eu acho que html é estranho aqui. Deve ser type = "button" por padrão, não enviando. É sempre inesperado para mim ver esse envio por padrão. É a exceção.
Http
31

Algum tempo atrás, eu precisava de algo muito semelhante ... e consegui.

Então, o que eu coloco aqui é como eu faço os truques para que um formulário possa ser enviado por JavaScript sem validar e executar validação somente quando o usuário pressiona um botão (normalmente um botão de envio).

Para o exemplo, usarei um formulário mínimo, apenas com dois campos e um botão de envio.

Lembre-se do que se deseja: No JavaScript, ele deve poder ser enviado sem nenhuma verificação. No entanto, se o usuário pressionar esse botão, a validação deverá ser feita e o formulário enviado somente se for aprovado na validação.

Normalmente, tudo começaria com algo próximo a isso (removi todas as coisas extras que não são importantes):

<form method="post" id="theFormID" name="theFormID" action="">
   <input type="text" id="Field1" name="Field1" />
   <input type="text" id="Field2" name="Field2" />
   <input type="submit" value="Send" onclick="JavaScript:return Validator();" />
</form>

Veja como a tag do formulário não tem onsubmit="..."(lembre-se de que era uma condição não a ter).

O problema é que o formulário é sempre enviado, independentemente de onclickdevoluções trueou false.

Se eu mudar type="submit"para type="button", parece trabalho, mas não o faz. Ele nunca envia o formulário, mas isso pode ser feito facilmente.

Então, finalmente, usei isso:

<form method="post" id="theFormID" name="theFormID" action="">
   <input type="text" id="Field1" name="Field1" />
   <input type="text" id="Field2" name="Field2" />
   <input type="button" value="Send" onclick="JavaScript:return Validator();" />
</form>

E function Validator, onde return True;está, também adiciono uma sentença de envio de JavaScript, algo semelhante a este:

function Validator(){
   //  ...bla bla bla... the checks
   if(                              ){
      document.getElementById('theFormID').submit();
      return(true);
   }else{
      return(false);
   }
}

O id=""é apenas para JavaScript getElementById, o name=""é apenas para que ele apareça nos dados do POST.

De tal maneira, funciona como eu preciso.

Coloquei isso apenas para pessoas que não precisam de onsubmitfunção no formulário, mas faço alguma validação quando um botão é pressionado pelo usuário.

Por que não preciso enviar submissões na tag de formulário? Fácil, em outras partes do JavaScript, preciso realizar um envio, mas não quero que haja nenhuma validação.

O motivo: se é o usuário que realiza o envio, desejo e preciso que a validação seja feita, mas se for JavaScript, às vezes, preciso fazer o envio, embora essas validações o evitem.

Pode parecer estranho, mas não quando se pensa, por exemplo: em um Login ... com algumas restrições ... como não permitir o uso de sessões PHP e nem os cookies são permitidos!

Portanto, qualquer link deve ser convertido para o envio desse formulário, para que os dados de login não sejam perdidos. Quando nenhum login ainda é feito, ele também deve funcionar. Portanto, nenhuma validação deve ser realizada nos links. Mas quero apresentar uma mensagem ao usuário se o usuário não tiver inserido os dois campos, user e pass. Portanto, se um estiver faltando, o formulário não deve ser enviado! existe o problema

Veja o problema: o formulário não deve ser enviado quando um campo estiver vazio somente se o usuário tiver pressionado um botão, se for um código JavaScript, ele deverá poder ser enviado.

Se eu fizer o trabalho na onsubmittag do formulário, precisarei saber se é o usuário ou outro JavaScript. Como nenhum parâmetro pode ser passado, isso não é possível diretamente, portanto, algumas pessoas adicionam uma variável para dizer se a validação deve ou não ser feita. A primeira coisa na função de validação é verificar o valor da variável, etc ... Muito complicado e o código não diz o que realmente é desejado.

Portanto, a solução é não enviar submissões na tag do formulário. A Insead coloca onde é realmente necessário, no botão.

Por outro lado, por que colocar código de submissão, pois, conceitualmente, não quero a validação de submissão? Eu realmente quero validação de botão.

Não apenas o código é mais claro, é onde deve estar. Lembre-se disso: - Não quero que o JavaScript valide o formulário (que deve sempre ser feito pelo PHP no lado do servidor) - Quero mostrar ao usuário uma mensagem informando que todos os campos não devem estar vazios, que precisa de JavaScript (cliente lado)

Então, por que algumas pessoas (pensam ou me dizem) isso deve ser feito com uma validação no local? Não, conceitualmente não estou realizando uma validação no cliente no lado do cliente. Estou apenas fazendo algo em um botão ser pressionado, então por que não deixar que isso seja implementado?

Bem, esse código e estilo funcionam perfeitamente. Em qualquer JavaScript que eu precise enviar o formulário, basta colocar:

document.getElementById('theFormID').action='./GoToThisPage.php'; // Where to go
document.getElementById('theFormID').submit(); // Send POST data and go there

E isso pula a validação quando eu não preciso. Apenas envia o formulário e carrega uma página diferente, etc.

Mas se o usuário clicar no botão enviar (também conhecido como type="button"não type="submit"), a validação será feita antes de permitir que o formulário seja enviado e, se não for válido, não será enviado.

Bem, espero que isso ajude outras pessoas a não tentar códigos longos e complicados. Só não use onsubmitse não for necessário e use onclick. Mas lembre-se de mudar type="submit"para type="button"e não se esqueça de fazer o submit()JavaScript.

z666zz666z
fonte
28

Eu concordo com o Shog9, embora eu possa usar:

<input type = "button" onClick="addItem(); return false;" value="Add Item" />

De acordo com o w3schools , a <button>tag tem um comportamento diferente em diferentes navegadores.

poundifdef
fonte
18

Suponha que seu formulário HTML tenha id="form_id"

<form id="form_id">
<!--your HTML code-->
</form>

Adicione esse snippet jQuery ao seu código para ver o resultado,

$("#form_id").submit(function(){
  return false;
});
Prateek Joshi
fonte
18

Você pode simplesmente obter a referência de seus botões usando o jQuery e impedir sua propagação como abaixo:

 $(document).ready(function () {
    $('#BUTTON_ID').click(function(e) {

            e.preventDefault();
            e.stopPropagation();
            e.stopImmediatePropagation();

            return false;
    });});
Ata Iravani
fonte
2
e.preventDefault(); e.stopPropagation();é suficiente para que as coisas funcionem. e.stopImmediatePropagation()isso gera um erro de método indefinido no Chrome.
Subroto
14

$("form").submit(function () { return false; }); isso impedirá o envio do botão ou você pode alterar o tipo de botão para "botão" em <input type="button"/>vez de <input type="submit"/> O que só funcionará se esse botão não for o único neste formulário.

Shiala
fonte
2
Isso é para jQuery, um equivalente em Javascript é: myform.onsubmit = function () {return false} ... também, mesmo que você remova o botão de envio, o formulário também pode ser enviado pressionando enter de outro campo de formulário.
Synexis
10

Este é um erro html5, como já foi dito, você ainda pode ter o botão como um envio (se quiser cobrir usuários javascript e não javascript) usando-o como:

     <button type="submit" onclick="return false"> Register </button>

Dessa forma, você cancelará o envio, mas continuará fazendo o que estiver fazendo nas funções jquery ou javascript e enviá-lo para usuários que não possuem javascript.

sagits
fonte
8

Estou certo de que no FF o

removeItem 

função encontrar um erro de JavaScript, isso não aconteceu no IE

Quando o erro do javascript aparecer, o código "return false" não será executado, tornando a página de postagem

Alin Vasile
fonte
8

O retorno false impede o comportamento padrão. mas o retorno false interrompe a interferência de outros eventos de clique. Isso significa que, se houver outras ligações de cliques após a chamada dessa função, essas outras não serão consideradas.

 <button id="btnSubmit" type="button">PostData</button>
 <Script> $("#btnSubmit").click(function(){
   // do stuff
   return false;
}); </Script>

Ou simplesmente você pode colocar assim

 <button type="submit" onclick="return false"> PostData</button>
Sunil Dhappadhule
fonte
7

Basta adicionar e.preventDefault();seu método para impedir que sua página envie formulários.

function myFunc(e){
       e.preventDefault();
}

De acordo com o MDN Web Docs

O método preventDefault () da interface Event informa ao agente do usuário que, se o evento não for processado explicitamente, sua ação padrão não deverá ser levada em consideração, como seria normalmente. O evento continua a se propagar como de costume, a menos que um de seus ouvintes chame stopPropagation ()ou stopImmediatePropagation (), um dos quais encerre a propagação.

Mselmi Ali
fonte
6

Defina seu botão da maneira normal e use event.preventDefault como ..

   <button onclick="myFunc(e)"> Remove </button>  
   ...
   ...

   In function...

   function myFunc(e){
       e.preventDefault();
   }
Vishal
fonte
4
return false;

Você pode retornar false no final da função ou após a chamada da função.

Contanto que seja a última coisa que acontece, o formulário não será enviado.

WonderWorker
fonte
2

Aqui está uma abordagem simples:

$('.mybutton').click(function(){

    /* Perform some button action ... */
    alert("I don't like it when you press my button!");

    /* Then, the most important part ... */
    return false;

});
axiom82
fonte
1

O código de exemplo a seguir mostra como impedir o clique no botão de enviar um formulário.

Você pode tentar o meu código de exemplo:

 <form autocomplete="off" method="post" action="">
   <p>Title:
     <input type="text" />
   </p>
   <input type="button" onclick="addItem()" value="Add Item">
   <input type="button" onclick="removeItem()" value="Remove Last Item">
   <table>
     <th>Name</th>

     <tr>
       <td>
         <input type="text" id="input1" name="input1" />
       </td>
       <td>
         <input type="hidden" id="input2" name="input2" />
       </td>
     </tr>
   </table>
   <input id="submit" type="submit" name="submit" value="Submit">
 </form>
<script language="javascript">
function addItem() {
return false;
}

function removeItem() {
return false;
}
</script>
The KNVB
fonte
0

Não estou conseguindo testar isso agora, mas acho que você poderia usar o método preventDefault do jQuery .

Tyler Rash
fonte
0

A função removeItem realmente contém um erro, o que faz com que o botão do formulário faça o comportamento padrão (enviando o formulário). O console de erro do javascript geralmente fornece um ponteiro nesse caso.

Confira a função removeItem na parte javascript:

A linha:

rows[rows.length-1].html('');

não funciona Tente isso:

rows.eq(rows.length-1).html('');
ylebre
fonte