Using PUT method in HTML form

后端 未结 7 2038
情话喂你
情话喂你 2020-11-22 11:30

Can I use a PUT method in an HTML form to send data from the form to a server?

相关标签:
7条回答
  • 2020-11-22 11:46

    According to the HTML standard, you can not. The only valid values for the method attribute are get and post, corresponding to the GET and POST HTTP methods. <form method="put"> is invalid HTML and will be treated like <form>, i.e. send a GET request.

    Instead, many frameworks simply use a POST parameter to tunnel the HTTP method:

    <form method="post" ...>
      <input type="hidden" name="_method" value="put" />
    ...
    

    Of course, this requires server-side unwrapping.

    0 讨论(0)
  • 2020-11-22 11:49

    for laraveling people

    <form method="post" ...>
    @csrf
    @method('put')
    ...
    </form>
    
    0 讨论(0)
  • 2020-11-22 11:52

    XHTML 1.x forms only support GET and POST. GET and POST are the only allowed values for the "method" attribute.

    0 讨论(0)
  • 2020-11-22 12:00

    Unfortunately, modern browsers do not provide native support for HTTP PUT requests. To work around this limitation, ensure your HTML form’s method attribute is “post”, then add a method override parameter to your HTML form like this:

    <input type="hidden" name="_METHOD" value="PUT"/>
    

    To test your requests you can use "Postman" a google chrome extension

    0 讨论(0)
  • 2020-11-22 12:07

    _method hidden field workaround

    The following simple technique is used by a few web frameworks:

    • add a hidden _method parameter to any form that is not GET or POST:

      <input type="hidden" name="_method" value="PUT">
      

      This can be done automatically in frameworks through the HTML creation helper method.

    • fix the actual form method to POST (<form method="post")

    • processes _method on the server and do exactly as if that method had been sent instead of the actual POST

    You can achieve this in:

    • Rails: form_tag
    • Laravel: @method("PATCH")

    Rationale / history of why it is not possible in pure HTML: https://softwareengineering.stackexchange.com/questions/114156/why-there-are-no-put-and-delete-methods-in-html-forms

    0 讨论(0)
  • 2020-11-22 12:08

    To set methods PUT and DELETE I perform as following:

    <form
      method="PUT"
      action="domain/route/param?query=value"
    >
      <input type="hidden" name="delete_id" value="1" />
      <input type="hidden" name="put_id" value="1" />
      <input type="text" name="put_name" value="content_or_not" />
      <div>
        <button name="update_data">Save changes</button>
        <button name="remove_data">Remove</button>
      </div>
    </form>
    <hr>
    <form
      method="DELETE"
      action="domain/route/param?query=value"
    >
      <input type="hidden" name="delete_id" value="1" />
      <input type="text" name="delete_name" value="content_or_not" />
      <button name="delete_data">Remove item</button>
    </form>
    

    Then JS acts to perform the desired methods:

    <script>
       var putMethod = ( event ) => {
         // Prevent redirection of Form Click
         event.preventDefault();
         var target = event.target;
         while ( target.tagName != "FORM" ) {
           target = target.parentElement;
         } // While the target is not te FORM tag, it looks for the parent element
         // The action attribute provides the request URL
         var url = target.getAttribute( "action" );
    
         // Collect Form Data by prefix "put_" on name attribute
         var bodyForm = target.querySelectorAll( "[name^=put_]");
         var body = {};
         bodyForm.forEach( element => {
           // I used split to separate prefix from worth name attribute
           var nameArray = element.getAttribute( "name" ).split( "_" );
           var name = nameArray[ nameArray.length - 1 ];
           if ( element.tagName != "TEXTAREA" ) {
             var value = element.getAttribute( "value" );
           } else {
           // if element is textarea, value attribute may return null or undefined
             var value = element.innerHTML;
           }
           // all elements with name="put_*" has value registered in body object
           body[ name ] = value;
         } );
         var xhr = new XMLHttpRequest();
         xhr.open( "PUT", url );
         xhr.setRequestHeader( "Content-Type", "application/json" );
         xhr.onload = () => {
           if ( xhr.status === 200 ) {
           // reload() uses cache, reload( true ) force no-cache. I reload the page to make "redirects normal effect" of HTML form when submit. You can manipulate DOM instead.
             location.reload( true );
           } else {
             console.log( xhr.status, xhr.responseText );
           }
         }
         xhr.send( body );
       }
    
       var deleteMethod = ( event ) => {
         event.preventDefault();
         var confirm = window.confirm( "Certeza em deletar este conteúdo?" );
         if ( confirm ) {
           var target = event.target;
           while ( target.tagName != "FORM" ) {
             target = target.parentElement;
           }
           var url = target.getAttribute( "action" );
           var xhr = new XMLHttpRequest();
           xhr.open( "DELETE", url );
           xhr.setRequestHeader( "Content-Type", "application/json" );
           xhr.onload = () => {
             if ( xhr.status === 200 ) {
               location.reload( true );
               console.log( xhr.responseText );
             } else {
               console.log( xhr.status, xhr.responseText );
             }
           }
           xhr.send();
         }
       }
    </script>
    

    With these functions defined, I add a event listener to the buttons which make the form method request:

    <script>
      document.querySelectorAll( "[name=update_data], [name=delete_data]" ).forEach( element => {
        var button = element;
        var form = element;
        while ( form.tagName != "FORM" ) {
          form = form.parentElement;
        }
        var method = form.getAttribute( "method" );
        if ( method == "PUT" ) {
          button.addEventListener( "click", putMethod );
        }
        if ( method == "DELETE" ) {
          button.addEventListener( "click", deleteMethod );
        }
      } );
    </script>
    

    And for the remove button on the PUT form:

    <script>
      document.querySelectorAll( "[name=remove_data]" ).forEach( element => {
        var button = element;
        button.addEventListener( "click", deleteMethod );
    </script>
    

    _ - - - - - - - - - - -

    This article https://blog.garstasio.com/you-dont-need-jquery/ajax/ helps me a lot!

    Beyond this, you can set postMethod function and getMethod to handle POST and GET submit methods as you like instead browser default behavior. You can do whatever you want instead use location.reload(), like show message of successful changes or successful deletion.

    =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

    JSFiddle: https://jsfiddle.net/enriquerene/d6jvw52t/53/

    0 讨论(0)
提交回复
热议问题