How should I handle the csrf_field() function when doing this with AJAX?
here is a link to the project repo.
Here is a link to the article which helped me write the code.
I'm pretty sure I don't have to make too many changes to the code to handle the forms with AJAX instead of regular blade.php form submissions, but I'm unsure of the implementation
<form id="add_item" method="POST" action="/item">
<div class="form-group">
<textarea name="item_name" placeholder='Enter your item'></textarea>
#if ($errors->has('item_name'))
<span class="text-danger">{{ $errors->first('item_name') }}</span>
#endif
</div>
<div class="form-group">
<button type="submit" >Add Item</button>
</div>
{{ csrf_field() }}
</form>
you can also put csrf-token in header file like this...
<meta name="csrf-token" content="{{ csrf_token() }}">
then give one unique id to submit button... then after in JavaScript detect that click event. then after call ajax on click event of submit button
$.ajax({
type: "POST",
// url: "{{ route('admin.users')}}" + id,
// url : '/admin/users/',
url: "{{url('admin/users/')}}", // you can pass url using url() OR as simple url OR Route name also
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') //get the Csrf token from header
},
data: { id: id, }, //pass here all data which you want to pass to controller
success: function (data) {
console.log(data);
}
});
get the csrf value using
var token = $('input[name="csrfToken"]').attr('value');
and append it to the header
$.ajax({
url: route.url,
data : JSON.stringify(data),
method : 'POST',
headers: {
'X-CSRF-Token': token
},
success: function (data) { ... },
error: function (data) { ... }
});
you can read more about it here https://stackoverflow.com/a/51964045/9890762
SOLVED.
I had to remove the 'type' attribute from the form as ajax is being used instead,
and ensure the ajax functions are at /public/js/file.js
Then, to make the changes available to the folder resources
npm run dev
<form id="add_item_form" action="/item">
<div class="form-group">
<textarea id="add_item_name" placeholder='Enter your item'></textarea>
#if ($errors->has('item_name'))
<span class="text-danger">{{ $errors->first('item_name') }}</span>
#endif
</div>
<div class="form-group">
<button id="ajaxSubmit_add">Add Item</button>
</div>
</form>
Related
I am using Laravel with AJAX to send form update request. With other method such as POST request, everything works fine. I managed to do Update method as well but with a different method which is defining it on data field one by one. But since my new form has a lot of input field, I try to serialize it using FormData, but then the error of target class does not exist came out. The error in specific is
Target class [App\Http\Controllers\Form] does not exist
The Controller that I am trying to send to is named FormController, somehow from the error it removes the "Controller" part.
I am not sure what causes it, hope someone would enlighten me on this issue, thank you.
Laravel Blade
<form enctype="multipart/form-data" id="formUpdate">
#csrf
<input type="hidden" name="flowId" id="flowId" value="1">
<input type="hidden" name="formId" id="formId" value="{{ $formData->id }}">
#component('components.form.form-section-a', ['formData' => $formData, 'projectMember' => $projectMember])
#endcomponent
<div class="grid w-full">
<div class="sm:px-1 md:px-0">
<button class="border-green-600 bg-green-600 w-full py-2 rounded mt-3 text-white submitForm" type="submit">Update</button>
</div>
</div>
</form>
AJAX Script
$("#formUpdate").on("submit", function (event) {
event.preventDefault();
var formId = $('#formId').val();
var url = '/Form/' + formId;
var form = this;
formData = new FormData(form);
console.log(Array.from(formData));
$.ajax({
url: url,
type: "PATCH",
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
data: formData,
// dataType:'json',
processData: false,
success: function (response) {
console.log(response);
// return false;
},
});
});
in your button add data-url="route('Form')" or console.log(url); first then check
This is my first api project. Can you help me with my code please?
I can't see the problem.
Here is my controller.
public function store(Request $request)
{
//
$valid=Validator::make($request->all(),[
'text'=>'required',
'body'=>'required'
]);
if($valid->fails()){
return response()->json(['message'=>$valid->messages()]);
}else{
$item= Item::create([
'text'=>$request->input('text'),
'body'=>$request->input('body')
]);
return response()->json($item);
}
}
and here is my form.Is there anything wrong in the form?
<form id="form">
<div class="form-group">
<label>Text :</label>
<input type="text" id="text" class="form-control col-sm-4">
</div>
<div class="form-group">
<label>Body :</label>
<textarea id="body" class="form-control col-sm-4"></textarea>
</div>
<div class="form-action">
<input type="submit" class="btn btn-primary" value="submit">
</div>
</form>
and the ajax code between the show function is working but I don't know where the problem is ?.
$('#form').on('submit', function (e) {
e.preventDefault();//prevent the form to submit to file
let text = $('#text').val();
let body = $('#body').val();
addItems(text, body);
});
function addItems(text, body) {
var item = {
text: text,
body: body
};
$.ajax({
method: 'POST',
url: 'http://localhost:8000/api/items',
data: item,
success: function (item) {
alert('done the item number' + item.id + ' has been added!!');
location.reload();
},
error: function () {
alert('error')
}
})
}
Thanks for helping!
if your front-end source separated from back-end source, then add cross-Origin Resource Sharing
package to your laravel project.
if its on your laravel view then add csrf token to meta tag -
<meta name="csrf-token" content="{{ csrf_token() }}">
and send it with your ajax request { _token : document.querySelector('meta[name="csrf-token"]').content}
The problem is that you're sending the form without sending the cross site request forgery token.
Add the directive #csrf to your view
Then send it has Hasan wrote ;)
Currently I am trying to pass a creation form to a controller. I have the route and the ajax call setup and talking to the route. My problem is that when I use the ajax call the inspect tool for headers is showing my form values correctly but when I go into the controller the request->input doesnt show any values for the form.
Here is my ajax call
$(document).on("click", ".form-submit-btn", function() {
// Get the form id.
var formID = $(this).closest("form").attr("id");
var serializedForm = $(this).closest("form").serialize();
var substringEnd = formID.indexOf("-form");
var route = formID.substr(0, substringEnd).replace("-", "_");
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
// Submit the form.
$.ajax({
method: "POST",
url: "/" + route,
data: {
serializedForm
},
success: function(data) {
alert(data);
}
});
});
Here is my controller
// Create Role
public function create(Request $request)
{
// Get and validate request params
$role = $request->input('role_name');
$active = $request->input('role-active', false);
return $role;
}
And here is my route
Route::post('/create_role', 'RoleController#create');
Am I missing something that is preventing the ajax call from sending the values to the controller
Here is my form also if that helps.
<form id="create-role-form" class="form">
{{ csrf_field() }}
<button class="pull-right right-close-btn">X</button>
<h1>Add Role</h1>
<hr />
<div class="form-group">
<label>Role Name</label>
<input type="text" name="role_name" class="form-control" />
</div>
<div class="form-group">
<input type="checkbox" name="role_active" value="true" checked /> Active
</div>
<div class="form-group">
<button class="btn btn-primary form-control form-submit-btn">Create</button>
</div>
I think problem is this line
data: {serializedForm},
Just change it to
data: serializedForm,
and it should fix the problem.
Problems
I see two problems with your ajax request
Are you sure you're using ES-6 TransPiler because data:{serializedForm}, is ES-6 Syntax http://es6-features.org/#PropertyShorthand
If you're javascript is working fine. You should be able to get it like $request->get('serializedForm')['role_name'] with your existing code.
Hope it helps
I'm trying to submit a form via ajax, but I'm always getting internal server error
Here is my form code
{!! Form::open(['route' => 'users.add', 'id'=>'form']) !!}
<!-- Solo moderador -->
<div class="card-panel">
#if(Auth::user()->permision->request == 1)
<p class="center">Observaciones del moderador:</p>
<textarea type="textarea" class="materialize-textarea" name="observations" id="updateObservations"></textarea>
#else
<div class="center">
<input type="checkbox" id="userVerify" class="filled-in">
<label for="userVerify">Problema solucionado :)</label>
</div>
</div>
#endif
{!! Form::close() !!}
Here is my route
Route::post('request/update', 'RequestsController#postUpdateRequest')->name('request.update');
Here is my Ajax method
$.ajax({
type: "post",
dataType: "html",
url: 'request/update',
data: $("#form").serialize(),
success: function (response) {
// write here any code needed for handling success
console.log("se envio");
}
});
and here is my method in the controller
public function postUpdateRequest(Request $request)
{
if($request->ajax())
{
// Obteniendo registro de la petición
$petition = Petition::where('id', $request->id)->first();
// Guardando
$petition->fill($request->all());
$auditConfirm = $petition->isDirty();
$petition->save();
// Guardando registro de auditorÃa
if($auditConfirm){
AuditsController::postAudit($this->action_id_update);
}
}
}
EDIT: This is the console output
Include this in your form:
echo Form::token();
Basically Laravel expects a CSRF token, middleware makes sure that token sent from form matches the token created before it.
If you don't want to add that on forum, you can add that in AJAX setup:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
..and have this in the HTML page header:
<meta name="csrf-token" content="{{ csrf_token() }}">
You are missing the CSRF token, Laravel has a method of handling this vulnerability via middleware, you have 2 options:
Add csrf token in html form:
{!! Form::open(['route' => 'users.add', 'id'=>'form']) !!}
<input type="hidden" name="_token" id="csrf-token" value="{{ Session::token() }}" />
Provide a global header when making a request:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
Read more
SOLVED:it seems that ive been missing the id value in the request all this time
I'm working on a screen with the following url http://localhost/npr/public/admin/athletes/test/143
On this screen, I've implemented the following dynamic droplist Ajax call that's not found:
$(document).ready(function() {
$('select[name="section"]').on('change', function() {
var sectionID = $(this).val();
if(sectionID) {
$.ajax({
url: './getSportPositions'+sectionID,
method: 'get',
//data: {"_token": $('#token').val()},
dataType: "json",
success:function(data) {
$('select[name="position"]').empty();
$('select[name="position"]').append('<option value="">'+ '-- Please choose one --' +'</option>');
$.each(data, function(i, position) {
$('select[name="position"]').append('<option value="'+position.name+'">'+ position.name +'</option>');
});
}
});
}else{
$('select[name="position"]').empty();
}
});
});
Route:
Route::get('getSportPositions{id}','HomeController#getSportPositions');
I've also tried with:
Route::get('/admin/athletes/test/getSportPositions{id}','HomeController#getSportPositions');
Is it due to athlete ID 143 in the calling URL? How do I fix this call?
It seems from the error that it's trying to access this route:
Route::get('/admin/athletes/test/{athlete}/', [
'uses' => 'HomeController#testAnAthlete',
'as' => 'admin.test_athlete'
]);
HTML:
<div class="form-group {{ $errors->has('position') ? ' alert alert-danger' : '' }}">
<label for="position" class="col-md-3 control-label">Position in Team</label>
<div class="col-md-6">
<select class="form-control" name="position" id="position">
#if (!$errors->has('position'))
<option selected value> -- select a team first -- </option>
#endif
</select>
</div>
#if ($errors->has('position'))
<span class="help-block">
<strong>{{ $errors->first('position') }}</strong>
</span>
#endif
</div>
When you are using Ajax you have to get url like
var APP_URL = $('meta[name="_base_url"]').attr('content');
also add this
<meta name="_base_url" content="{{ url('/') }}">
to head tag
then after you can use APP_URL
var url = APP_URL+"/getSportPositions/"+sectionID;
Additional from me. in laravel view :
<meta name="_base_url" content="{{ url('/') }}">
<meta name="csrf-token" content="{{ csrf_token() }}">
in addition to #Nikhil Radadiya answer, because using jquery mean you wait for page ready, you can use javascript :
var APP_URL = document.getElementsByTagName('meta')._base_url.content;
var APP_CSRF = document.querySelector("meta[name='csrf-token']").content; // javascript cannot use dash, else you can use csrf_token at meta name
then you can use in your ajax like :
$.ajax({
headers: {
'X-CSRF-TOKEN': APP_CSRF
},
url: APP_URL + '/your_ajax_path',
...
...
});
and make sure the url is loaded in your web route.
You could name the route and use BLADE to set a Javascript variable to that route.
For example:
Route::get('/', 'MyAmazingController#function')->name('my.awesome.route');
Then in your Javascript you can do something like:
url: '{{ route('my.awesome.route') }}';
If you have the javascript in a seperate file, you could create a constant in your view with routes in it.
val ROUTES = {
AJAX: '{{ route('my.awesome.route') }}'
}