2

I am converting a procedural PHP application into a RESTful Laravel/jQuery application. I have done some extensive research, but all suggestions have failed and are included below.

In the old version creation of a new record was done by GETting the page URL with ?Add as a GET variable:

<div class="dropdown">
    <button id="BtnID">File</button>
    <div class="dropdown-content">
        <a href="./?Add">Add New</a>
        <a href="...">More menu items</a>
    </div>
</div>

As per Laravel standards I am attempting to POST a request to the page, so I have altered the menu as:

<div class="dropdown">
    <button id="BtnID">File</button>
    <div class="dropdown-content">
        <form id="AddNew">
            <!--<a id="Add" href="#">Add New</a>-->
            <!--input type='button' id='Add' value='Add New' /><!--Suggested change - also not working-->
            <input type='submit' id='Add' value='Add New' /><!--Another suggested change - also not working-->
        </form>
        <a href="...">More menu items</a>
    </div>
</div>

jQuery:

$('#Add').on('click',function(e) {
    e.preventDefault;
    if(confirm('some text'))
        $('#AddNew').submit();
    return false;
});
$('#AddNew').append(CSRF);
$('#AddNew').attr('action','./');
$('#AddNew').attr('method','post');

Can anyone help me figure out why this form refuses to POST the request? The confirmation message appears and then navigates to the correct page, but application makes a GET request to it? I have noticed the CSRF token input is not displayed in the URL, as I would expect for a GET request.

EDIT As requested here are the routes associated to this page:

//  Route::get('/SubDirectory/ThisPage/','ThisController@index'); Usually forwards to first page, but commented out for testing this
    Route::get('/SubDirectory/ThisPage/{PageNr}', 'ThisController@edit');
    Route::post('/SubDirectory/ThisPage/', 'ThisController@add');
    Route::delete('/SubDirectory/ThisPage/{ID}', 'ThisController@destroy');
    Route::patch('/SubDirectory/ThisPage/{ID}', 'ThisController@update');
Dominik
  • 21
  • 6
  • [Does this help?](https://stackoverflow.com/a/4286493/6463262) – KiprasT Dec 10 '19 at 12:51
  • The default HTTP method is `GET`, you have to specify in your `HTML` `
    ...
    ` and it shoud be submitted via `POST`
    – toffler Dec 10 '19 at 12:54
  • I have specified the POST method in jQuery... $().attr('method','post') – Dominik Dec 10 '19 at 12:55
  • Hmm... if in javascript, I think the cleaner way is to set the method in the `submit` event handler: `$('#AddNew').on('submit',function(){ $(this).attr('method','post'); });` – toffler Dec 10 '19 at 13:05
  • Are you sure that you have only one `#AddNew` form on the page? The way you are using it suggests that you have multiple forms. Can it be the cause? – dkasipovic Dec 10 '19 at 13:05
  • Thanks, I'll bear that in mind, when I finally get the request working. Also all IDs are unique... the menu item anchors have a different ID to their corresponding forms – Dominik Dec 10 '19 at 13:11
  • Try replacing `./` to `/` only –  Dec 10 '19 at 14:14
  • That will navigate to the site root, which is definitely not what I want... – Dominik Dec 10 '19 at 14:17
  • Is this the route you're submitting the form to? `Route::post('/SubDirectory/ThisPage/', 'ThisController@add');` –  Dec 10 '19 at 15:25
  • Yes, this is the destination of the form - "./" I get a Laravel routing error stating the destination only accepts POST requests, because the request is not being POSTed. – Dominik Dec 10 '19 at 15:38

3 Answers3

0

HTML forms are submitted using inputs or buttons with submit types. You should not use links to submit forms, yet if you are so keen on submitting a form with a link you can use a link with attribute onclick="form.submit();". Note that if you use this method, it will not work for users that do not support javascript.

KiprasT
  • 370
  • 5
  • 14
  • The onclick handler contains this: $('#Add').on('click',function(e) { e.preventDefault; if(confirm('some text')) $('#AddNew').submit(); return false; }); – Dominik Dec 10 '19 at 13:07
  • Why? Why not just a simple ``? If further down the road you will need to do some asynchronous request or what not, then give the input an id... – KiprasT Dec 10 '19 at 13:12
  • Because I am attempting to re-use the existing menu formatting. If I convert the anchor tags to buttons/inputs, the styling doesn't have the same effect. – Dominik Dec 10 '19 at 13:15
  • You can style an input any way you would like to. – KiprasT Dec 10 '19 at 13:16
  • I have just converted the anchors to submit inputs and the page still sends a GET request – Dominik Dec 10 '19 at 13:21
0

I think you are missing CSRF token which is causing issue. Working example is here

$('#Add').on('click',function(e) {
    e.preventDefault;
    if(confirm('some text'))
        $('#AddNew').submit();
    return false;
});

$(document).ready(function(){
  $('#AddNew').append('<input type="hidden" name="_token" value="'+$('meta[name="csrf-token"]').attr('content')+'" />');
  $('#AddNew').attr('action','./');
  $('#AddNew').attr('method','post');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
  <head>
    <title>Title</title>
    <meta name="csrf-token" content="73ijdnnxyis7o3jr">
  </head>
  <body>
  <div class="dropdown">
    <button id="BtnID">File</button>
    <div class="dropdown-content">
        <form id="AddNew">
            <a id="Add" href="#">Add New</a>
        </form>
        <a href="...">More menu items</a>
    </div>
</div>
  </body>
</html>
0

I have discovered this doesn't like using './' as the action target. I changed the action attribute to the full URL '/SubDirectory/ThisPage' and this now works.

Dominik
  • 21
  • 6