Saiyan Prince
Saiyan Prince

Reputation: 4020

Submit form using VueJs and AJAX in Laravel 5.1

I am trying to submit a form using AJAX and VueJs. But somehow I am failing to achieve that. I always end up getting an empty Illuminate\Http\Request object.

The blade file:

<body>
    <div class="container">
        <generate-admin></generate-admin>
    </div>

    <script src="https:http://code.jquery.com/jquery.js"></script>
    <script src="{{ url('/js/main.js') }}"></script>
</body>

The component:

<template>
    <form id="createAdministrator" @submit.prevent="createAdministrator">

        <div class="form-group">

           <input type="text"
                  name="username"
                  id="txtUserName"
                  placeholder="Username"
                  autocomplete="off"
                  v-model="username"
           />

        </div>

        <input type="submit" value="Submit">

    </form>
</template>

<script>
    export default {
        data: function() {
            return {
                username: ''
            }
        },

        methods: {
            createAdministrator: function() {
                formContents = jQuery("#createAdministrator").serialize();

                this.$http.post('/admin', formContents).then(function(response, status, request) {
                    console.log(response);
                }, function() {
                    console.log('failed');
                });
            }
        }
    }
</script>

main.js

import Vue from 'vue';
import GenerateAdmin from './components/GenerateAdmin.vue';

var VueResource = require('vue-resource')
Vue.use(VueResource);

Vue.http.headers.common['X-CSRF-TOKEN'] = document.querySelector('#token').getAttribute('content');
Vue.http.options.emulateJSON = true;

new Vue({
    el: 'body',

    components: { GenerateAdmin }
});

gulpfile.js

var elixir = require('laravel-elixir');

require('laravel-elixir-vueify');

elixir(function(mix) {
    mix.browserify('main.js');
});

routes.php

Route::get('/admin/create', function () {
    return view('admin.create');
});

Route::post('/admin', function(Request $request) {
    // returns an empty object.
    return response(['results' => $request]);
});

Route::get('/', function () {
    return view('welcome');
});

What I get in return is:

"{"results":{"attributes":{},"request":{},"query":{},"server":{},"files":{},"cookies":{},"headers":{}}}"

When I check the Request Payload section of Network Tab in Chrome. I do see that the form is getting submitted successfully with whatever data I write in the text box above.

Why is this happening ? Kindly guide me where I have made the mistake ?


UPDATE 1:

I was playing trial and error with the code above. And I removed the namespace Illuminate\Http\Request and also removed the argument Request $request from the post Route. And changed the passing parameter to object from string.

Doing so, did the job for me that I was looking for. Why I don't know. I am still looking for someone who can explain this to me.

Why adding the namespace Iluminate\Http\Request in routes.php file didn't work as I was expecting and removing it did the task ?

Can anybody tell me why it didn't worked out earlier ? Any kind of help is highly appreciated.


P.S.: I have started learning VueJs Components recently.

Upvotes: 3

Views: 6502

Answers (2)

Donkarnash
Donkarnash

Reputation: 12835

As a general practice I follow, any form data which needs to be passed to the laravel controller is passed as json object from vue frontend. Then in laravel controller (route with a closure function in your case) the values from the received json object are retrieved by using $request->get('key').
So in your case the component code could be

    <template>
    <form id="createAdministrator" @submit.prevent="createAdministrator">

        <div class="form-group">

           <input type="text"
                  name="username"
                  id="txtUserName"
                  placeholder="Username"
                  autocomplete="off"
                  v-model="username"
           />

        </div>

        <input type="submit" value="Submit">

    </form>
</template>

<script>
    export default{
      template:require('./generate-admin-template.html'),
      data() {
          return {
              username: ''
          }
      },
      computed:{
        formData(){
          return {
            username:this.username
          }
        }
      },
      methods: {
          createAdministrator: function() {
              this.$http.post('/admin', this.formData).then(function(response) {
                  console.log(response);
              }, function() {
                  console.log('failed');
              });
          }
      }
    }
</script>

Then in your routes.php file

<?php
use Illuminate\Http\Request;

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::get('/admin/create', function () {
    return view('admin.create');
});

Route::post('/admin', function (Request $request) {
    return response(['results' => $request->get('username')]);
});  

I guess the Illuminate\Http\Request instance returns a $request - Collection so we need to access the values using Methods available on Collections.
I have tested the above code along with your code for main.js and '/admin/create'.
One more thing - I think if you send serialized form data to the controller, then within the controller it needs to be de-serialized in order to get object or array containing $key=>$value pairs to facilitate fetching required data.

Upvotes: 2

Mikhail Kozlov
Mikhail Kozlov

Reputation: 31

All variables ($attributes, $request, $query, etc) on Request and SymfonyRequest classes are protected, since neither class implements __toString, php does its best to give you what it can.

If you need to see each value, you need to call correct getter. Something like:

Route::post('/admin', function(Request $request) {    
    return response(['server' => $request->server(), 'form'=>$request->all()]);
});

Upvotes: 0

Related Questions