2

I am trying to pass data from Javascript code to a Controller but I cant get the variables data in the Controller Code.

I have a view that has a Js file associated that checks when the submit button is clicked and creates some arrays with data to be sent to the server.

I have tried a lot of solutions (commenting the form and defining a attribute to the button with the URL, using the form post action , using $.post in javascript) but i cant seem to get it working.

I have included code to better illustrate what I am trying to do.

Import View code:

   <form id="importar" class="form-horizontal" role="form" method="POST" action="{{ url('/importarLista1') }}">
       {{ csrf_field() }}
        <input type="text" class="form-control" name="startFrom" id="startFrom" value="">
    <div class="col-md-4">
        <button class="btn btn-primary" id="importar" data-href="{{ url('/importarLista1') }}">
            <i class="fa fa-btn fa-sign-in"></i>Importar
        </button>
    </div>
      </form>

JavaScript Code:

  var fdata=  "startFrom="+ startFrom;
      fdata+=   "&idList="+ idList;
      fdata+=   "&nomeCampos="+ nomeCampos;
        fdata+=    "&posicaoCampos="+ posicaoCampos;
 $.ajax({
        type:'POST',
        url: $( this ).attr( 'data-href' ) /*$( this ).prop( 'action' ) $( this ).attr( 'data-href' )*/,
      data:fdata,
        dataType:'json',
    cache:false,
    success:function (data){
    alert(data);
    }

});

nomeCampos and posicaoCampos are arrays created using javascript and have values assigned to them so they are not empty

JavaScript Code Edit1 Updated code from answer

$('#importar').submit(function() {
    if($('#startFrom').val()=='') {
        var startFrom = 0;
    }else{
        var startFrom = $('#startFrom').val();
    }
    var nomeCampos = new Array();
    var posicaoCampos = new Array();
    $('tbody tr').each( function(){
        $('td', this).each(function(e){
            posicaoCampos[e] = $(this).attr('idc');
        });
        return false;
    });

    var idList = $('#idList').val();
    var fdata= "_token="+ $( this ).find( 'input[name=_token]' ).val();
    fdata+=  "&startFrom="+ startFrom;
    fdata+=   "&idList="+ idList;
    fdata+=   "&nomeCampos="+ nomeCampos;
    fdata+=    "&posicaoCampos="+ posicaoCampos;
    e.preventDefault();

    $.post( // short hand for  $.ajax({ type:'POST'
        $(this).attr('action'), // url, from form
        $(this).serialize(), // form data, name and value
        function(data) {
            // on success...
            alert(data);
        }
    );
}); // end form.submit

Controller Code

  protected function importList1(Request $request){
    echo $_POST['startFrom'];
    exit();
    if($request->ajax()) {
        $data = Input::all();
        print_r($data);die;
    }
    print_r($request->all());
}

Route

Route::post('/importarLista1','ContactsList\ContactListController@importList1');

Example Solution This is what my final code looks like

JavaScript

 function preparePostData(){
        var token         = $( '#importar' ).find('input[name=_token]').val();
        var startFrom     = 0;
        var idList        = $('#idList').val();
        var nomeCampos    = new Array(); // not sure where this is getting used?
        var posicaoCampos = new Array();

        if($('#startFrom').val()=='' || $('#startFrom').val()<=0 ) {
            var startFrom = 0;
        }else{
            var startFrom = $('#startFrom').val()-1;
        }
        var nomeCampos = new Array();
        var posicaoCampos = new Array();

        $('thead tr th').each(function(e){
         for(var i = 0; i < nomeCampos.length; i++){
         if(nomeCampos[i]==$('select', this).val()){
         $.Notification.autoHideNotify('error', 'top right', 'STATUS', 'Não pode selecionar Campos Iguais');
         exit();
         }
         }
         nomeCampos[e] = $('select', this).val();
         });

        $('tbody tr').each( function(){
            $('td', this).each(function(e){
                posicaoCampos[e] = $(this).attr('idc');
            });
            return false;
        });
        var file_data=$('input:file')[0].files;
        var postdata=new FormData();
        postdata.append('_token',token);
        postdata.append('startFrom',startFrom);
        postdata.append('idList',idList);
        postdata.append('nomeCampos',nomeCampos);
        postdata.append('posicaoCampos',posicaoCampos);
        postdata.append('file',file_data[0]);
        return postdata;
    }

 $('#importar').submit(function(e) {
       e.preventDefault();
           fdata=preparePostData();
        $.ajax({
            type:'POST',
            url:   $(this).prop('action'), // url, from form
            data:fdata,
            processData: false,
            contentType: false,
            success:function(data) {
                window.location.replace(data.url);
            }
        });
    }); // end form.submit

Controller

 if ($request->session()->token() !== $request->get('_token')) {
        return Response::json(array(
            'status' => 'error',
            'msg' => 'Invalid token'
        ));
    }
    $idCompany = $request->session()->get('current_company');
    $skipValue = $request->get('startFrom');
    $idList = $request->get('idList');
    $arrayPos = $request->get('posicaoCampos');
    $arrayCampos = $request->get('nomeCampos');

And do what you need to do

Cœur
  • 37,241
  • 25
  • 195
  • 267
Diogo Silva
  • 39
  • 1
  • 13
  • You can use `$request->input('startFrom')` instead of using `Input::get` and/or `$_POST` – Ash Feb 22 '16 at 14:03

1 Answers1

3

This is my approach when using forms for ajax in a laravel application, as I'm sure it is for many others...

You have your form:

HTML

<form id="importar" class="form-horizontal" role="form" method="POST" action="{{ url('/importarLista1') }}">
    {{ csrf_field() }}

    <input type="text" class="form-control" name="startFrom" id="startFrom" value="">

    <div class="col-md-4">
        <button class="btn btn-primary" id="importar" data-href="{{ url('/importarLista1') }}">
            <i class="fa fa-btn fa-sign-in"></i>Importar
        </button>
    </div>
</form>

if you're submitting all your data from one form, rather than doing this to prep your data:

var fdata=  "startFrom="+ startFrom;
    fdata+=   "&idList="+ idList;
    fdata+=   "&nomeCampos="+ nomeCampos;
    fdata+=    "&posicaoCampos="+ posicaoCampos;

You can instead listen for the form submission (You may need to update/add to the form's button to type="submit") and use the serialize() method to grab all the data. (This would of course only work if everything is in one form and it's not clear to me if that is the case for you.)

So you could do something like this:

JS

$('form').submit(function() {
    e.preventDefault();

    $.post( // short hand for  $.ajax({ type:'POST'
        $(this).attr('action'), // url, from form
        $(this).serialize(), // form data, name and value
        function(data) { 
            // on success...
            alert(data);
        }
    );
}); // end form.submit

PHP/Controller code

protected function importList1(Request $request){

    // return the data back as ajax
    return response()->ajax([
        'data' => $request->all()
    ]);

}

Hope that helps!

Some extra advice, when getting started with using laravel and ajax together, if on chrome, you want to get the developer tools open. You can of course use firebug in firefox.

Using the developer tools, before hitting submit on your form, check the network tab then hit submit and see what happens. You should see a new post request. You can then click on the post request your form creates in the network tab to inspect what is going on and what comes back.

In short, the developer tools are invaluable for debugging ajax requests, because you will not get any feedback on the screen. You may also want to check out the chrome extension named postman for testing your ajax requests.

Edit

As you're not solely using the form for the data in your post call, serializing the form data won't be sufficient.

I extracted your code to prepare the data for the post call to a separate function to make it more readble and called the function when the form is submitted.

The data is passed to the $.post method as an object rather than a string.

I wrote the code just in my text editor, I didn't test it out. So there may be some mistakes, try and play around with it if you encounter any.

JS

$('#importar').submit(function() {

    e.preventDefault(); // stop the form from submitting data 

    // prep data for ajax post
    var postData = preparePostData(); // call function to get data

    // perform ajax post
    $.post( // short hand for  $.ajax({ type:'POST'
        $(this).attr('action'), // url, from form
        postData, // form data, name and value
        function(data) {
            // on success...
            alert(data);
        }
    );
}); // end form.submit

function preparePostData() {
    var token         = $( this ).find('input[name=_token]').val();
    var startFrom     = 0;
    var idList        = $('#idList').val();
    var nomeCampos    = new Array(); // not sure where this is getting used?
    var posicaoCampos = new Array();

    if ($('#startFrom').val()=='') {
        var startFrom = 0;
    } else {
        var startFrom = $('#startFrom').val();
    }

    $('tbody tr').each( function(){
        $('td', this).each(function(e){
            posicaoCampos[e] = $(this).attr('idc');
        });

        return false;
    });

    var postData = {
        _token: token,
        startFrom: startFrom,
        idList: idList,
        nomeCampos: nomeCampos,
        posicaoCampos: posicaoCampos
    };

    return postData;
}
haakym
  • 12,050
  • 12
  • 70
  • 98
  • I tried what you said and i can get the values that are from form elements but the variables are not there, maybe the problem is that the arrays are not elements (as in HTML elements)? I'll update the JS code in the question so you can have an idea what i'm talking about – Diogo Silva Feb 22 '16 at 12:56
  • 1
    Updated the code at original post , should i put fdata inside serialize? – Diogo Silva Feb 22 '16 at 13:02
  • As I mentioned in the answer "if you're submitting all your data from one form", if you're not (which it doesn't look like you are) then just alter the second argument to the way you were passing the data before. Alternatively you could pass it as a JSON object, I'll update my answer in a sec to show you that way. – haakym Feb 22 '16 at 13:03
  • @DiogoSilva I've updated my answer, I hope it all makes sense? – haakym Feb 22 '16 at 13:36
  • First of all thanks for your time :). I have played around with your code and it makes perfect sense but im still only getting the form token and startFrom value im trying to use firebug to see whats going on... – Diogo Silva Feb 22 '16 at 14:22
  • Thank you, my pleasure to help. Hmm that's weird! Seems like some good debugging will solve the issue. What I'd do in this situation is `console.log()` whatever you're passing to the `$.post` method as the second argument *before* calling the `$.post` method. It's definitely worth double checking that you are definitely not passing `$(this).serialize()` to the `$.post` method if you're only getting the `_token` and `startFrom` key/values. Please also note that when you are debugging ajax requests you can see 1. what's being sent and 2. what's returned back. Check what's being sent as well. – haakym Feb 22 '16 at 14:29
  • 1
    thank you this was the right answer i'll post the solution later – Diogo Silva Feb 22 '16 at 15:41
  • Great stuff! Glad you got it working in the end. Just a word of advice regarding your JS, do check out something like a jslint plugin for your editor, as it will help you write better more readable code. Happy coding. – haakym Feb 22 '16 at 15:51