Submit form using VueJs and AJAX in Laravel 5.1 - php

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.

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.

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()]);
});

Related

Passing a PHP variable to Vue component as prop doesn't work

I'm trying to pass a string from a laravel blade to a vue component but vue keeps telling me that the variable is undefined. I've tried every solution and nothing seems to work.
header.blade.php
<div id='app'>
<header-component page="{{$page}}"/>
</div>
headerComponent.vue
<button v-on:click="toggleForm"> TEST </button>
<script>
export default {
props: {
page: String
},
data() {
return {
//
}
},
methods: {
toggleForm: function() {
console.log(this.page);
}
}
}
</script>
I also tried
props: ['page'],
and
<header-component :page="'{{$page}}'"/>
and yes the $page variable does show a string when I dd($page)

Laravel autocomplete 404 (Not Found)

So i am noob working with laravel, i have try find a solution but i can not find out.
I am making a autocomplete in laravel.
My route:
Route::get('autocomplete',array('as'=>'autocomplete','uses'=>'SearchController#autocomplete'));
My SearchController:
public function autocomplete(Request $request)
{
$data = Country::select("name")->where("name","LIKE","%{$request->input('query')}%")->get();
return response()->json($data);
}
My script:
<script type="text/javascript">
var path = "{{ route('autocomplete') }}";
$('input.typeahead').typeahead({
source: function (query, process) {
return $.get(path, { query: query }, function (data) {
return process(data);
});
}
});
And finaly my input:
input class="typeahead form-control" id="front-item-field" placeholder="{{trans('messages.home.where_want_to_go')}}" name="item" type="text" required>
The error:
GET http://xxxxx.com/autocomplete?query=p 404 (Not Found)
Well i have made a mistake the route was inside of a route group for auth user, so i have change the line of the route to evry one can see and works like a charm.

Updating content Laravel

I want to make a feature for my web app in laravel(i'm new at it) that every Post/Comment/Theme(in my case) the user has the ability to upVote and downVote. Now i am woking with upVote, but it is not working whatsoever.
In the view (welcome.blade.php)
I have:
<img class="media-object" style="height:40px; width:40px;" src="images/upVote.svg" alt="...">
Where $Theme->name is the one that the user wants to upVote/like(whatsoever).
The route:
Route::put('/', [
'uses'=>'Vote#VotePlus',
'as' =>'Voteplus' //Name of route
]);
And the controller:
<?php
namespace App\Http\Controllers;
use App\NewTheme;
use DB;
class Vote extends Controller {
public function VotePlus($name){
DB::table('New_Themes')
->where('name', $name)
->increment('upVotes', 1);
$Themes = NewTheme::paginate(5);
return redirect()->route('welcome', ['Themes'=>$Themes]);
}
};
I am trying everything, but it isn't working. Can someone help me please?
With an anchor tag, you only send a get request. If you want it to be put, you must create a form, and then add :
<input type="hidden" name="_method" value="PUT">
Another way to solve this issue is to use Ajax. Right now the page will get refreshed each time a user wants to up-vote a theme and that can be quite frustrating.
I think you should post to the back end using Ajax and on the success callback update the view with javascript. I recommend using Angular for the front end. It has all what you need and it is super simple to make an Ajax-request.
So, here's a quick example how you could use Angular + Laravel to make your web application work.
Front End
<html ng-app="exampleApp">
<head>
<title>MyTitle</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body>
<div ng-controller="ThemeController">
<ul>
<li ng-repeat="theme in themes">
<span><% theme.name %></span>
<p><% theme.description %></p>
<p><% theme.votes %></p>
Vote Up
</li>
</ul>
</div>
<script type="text/javascript">
var app = angular.module("exampleApp", [], function($interpolateProvider) {
// This we need to not collide with Laravel's {{ }}
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
});
app.controller('ThemeController', function($scope, $http) {
$scope.themes = [];
$scope.voteUp = function(theme) {
$http({
url: '/api/themes/voteUp',
method: 'POST',
data: {
id: theme.id
}
}).success(function(response) {
theme.votes += 1;
});
}
// On init we need to get the themes
$http({
url: '/api/themes',
method: 'GET'
}).success(function(themes) {
$scope.themes = themes;
});
});
</script>
</body>
</html>
Back End
Your routes
Route::get('api/themes', 'ThemeController#getFive');
Route::post('api/themes/voteUp, 'ThemeController#voteUp');
Your ThemeController
function getFive() {
return Theme::paginate(5);
}
function voteUp(Request $request) {
$theme = Theme::whereId($request->id);
$theme->votes += 1;
$theme->save();
return $theme;
}
This code is not tested. But I'll think you get the point!

500 internal server error while posting data to database with laravel 5 and ajax

Hi guys? am trying to post data to the database using laravel 5 and ajax..am also applying using csrf protection by adding
<meta name="_token" content="{!! csrf_token() !!}"/>
to my layout header and adding the following code to my footer:
<script type="text/javascript">
$.ajaxSetup({
headers: { 'X-CSRF-Token' : $('meta[name=_token]').attr('content') }
});
</script>
This is my form:
<form action="{{action('QuizController#postQuiz')}}" method="POST">
<div id="name-group" class="form-group">
<label for="name">Please type your question here</label>
<input type="text" class="form-control" name="question">
</div>
<button type="submit" class="btn btn-success">Submit <span class="fa fa-arrow-right"></span></button>
</form>
This is my JS code:
var formData = {
'question' : $('input[name=question]').val(),
};
// process the form
$.ajax({
type : 'POST',
url : 'quiz',
data : formData,
dataType : 'json',
encode : true
})
// using the done promise callback
.done(function(data) {
// log data to the console to see
console.log(data);
// ALL GOOD! just show the success message!
$('form').append('<div class="alert alert-success">' + data.message + '</div>');
// stop the form from submitting the normal way and refreshing the page
event.preventDefault();
This is my route:
Route::post('create/quiz', array(
'as' => 'post-quiz',
'uses' => 'QuizController#postQuiz'
));
When my controller is like the following:
public function postQuiz()
{
if(Request::ajax()) {
$question = Request::get('question');
$data['success'] = true;
$data['message'] = $question;
echo json_encode($data);
}
the ajax call works and it returns,
Object {success: true, message: "test question"}
but when I try posting data to the database using:
public function postQuiz()
{
if(Request::ajax()) {
$question = Request::get('question');
DB::table('questions')->insert([
'question' => $question,
]);
}
I get the following from the console
POST http://localhost/leoschool-laravel5/public/create/quiz 500 (Internal Server Error)
and
Object {readyState: 4, responseText: "{"success":true,"message":"test question"}<!DOCTYPE htm…l>↵</div>↵↵ </div>↵ </body>↵</html>", status: 500, statusText: "Internal Server Error"}
What could be the problem? Thanks..
A good place to start is with Chrome Developer tools. Load your page with the tools open and fire the event that does the AJAX request.
Under the network tab of the tools, it will show you every request made and allow you to preview the response as if you were not using AJAX. This will show you the laravel stack trace. I think the problem is that you're using facades and they're not namespaced correctly.
Change your controller function to this and see if it works:
public function postQuiz()
{
if(\Request::ajax()) {
$question = \Request::get('question');
\DB::table('questions')->insert([
'question' => $question,
]);
}
With the above instruction on how to use dev tools and with the corrected code, you should be able to fix your problem. A better way to write this code would look like this though:
// assuming you have these models setup
// this uses dependency injection
public function postQuiz(Request $request, Question $question)
{
if($request->ajax()) {
$newQuestion = $request->get('question');
//add fields here to create new question with
$question->create([ /*stuff*/ ]);
}

how to get json encode from render function in symfony2

I'm trying to work with ajax in symfony but is some hard for me. I have a form in twig where I get a value that I'm using for search a product in my database:
This is the form in twig:
<form id="myForm" method="post" action="{{ path('my_app_greeting') }}">
<div class="input-group">
<input id="name_id" name="name" type="text" class="form-control" placeholder="Buscar repuesto..." required />
<span class="input-group-btn">
<button id="search-button" class="btn btn-default" type="button">Buscar</button>
</span>
</div><!-- /input-group --></br>
</form>
This is my code using jquery in the same twig template for send the data with ajax:
$(document).ready(function(){
$("#myForm").submit(function(){
var value = $("#name_id").val();
$.ajax({
type: "POST",
data: { productValue: value },
url: "/ventas/test/ajax/"
})
.done(function(response){
template = response;
$('#output').html(template.content);
})
.fail(function(jqXHR, textStatus, errorThrown){
alert('Error : ' + errorThrown);
});
return false;
});
});
Later I read about how symfony works with ajax and I thought the best solution for my "problem" is create a new twig template called "ajaxContent.html.twig" for example and do this with the controller:
public function testAction()
{
$request = $this->get('request');
$name = $request->request->get('productValue');
$template = $this->renderView('AcmeDemoTwoBundle:Ventas:ajaxContent.html.twig', array('value' => $name));
$json = json_encode($template);
$response = new Response($json, 200);
$response->headers->set('Content-Type', 'application/json');
return new Response($response);
}
Of this way later I want to put all the html content inside my original template but I have a problem with json encode. I don't understand very well how it works and how is the better way for receive the data and show it in the twig template. How can I do this? ( I tried to show the data using $('#output').html(template.content); but doesn't work).
Thanks for your help!
Your code in controller seems to be not good.
I mean if you want to return json then what for do you render html (not json) twig template? That's the first.
Then you can get json response by using JsonResponse instead of setting header for standard response.
I don't know what's happening in ajaxContent.html.twig, but I would do something like this:
public function testAction(Request $request)
{
$name = $request->get('productValue');
$response = $this->get('my_response_sercive')->giveMeResponseForTestAction($name);
return new JsonResponse($response);
}
If you are waiting for html response in you javascript you have to set option dataType: 'html' for your ajax request.
Then in testAction you don't have to set 'application/json' header and don't have to json_encode $template variable - but just render your template as you are doing it now.
So in this case you could do something like this:
public function testAction(Request $request)
{
$name = $request->get('productValue');
return $this->renderView('AcmeDemoTwoBundle:Ventas:ajaxContent.html.twig', array('value' => $name));
}
After that you can put html into your #output block directly:
$('#output').html(response);
You should use form array first for your problem try this
$template['content']

Categories