Make button do Controller method without changing page - Laravel - php

Hello I'm trying to make a button that once clicked I save the information written in the text field plus the current user logged in ID.
Once clicked just refresh the page (or just do nothing) and save that information in the database.
But my button is doing nothing...
My Controller:
public function addSchool(Request $request)
{
DB::table('schools')->insertGetId([
'id_professor' => Auth::id(),
'escola' => $request->input('escola')
]);
return redirect('/teacher');
}
My zone where i have the textfield and button:
<div class="form-group">
<h3 style="color: #000000" for="escola">Nome da Escola</h3>
<input type="text" id="escola" name="escola" class="form-control">
</div>
<div>
<button type="submit" class="btn btn-danger">Registar Escola</button
</div>
I didn't add any web.php (routes file) here because i don't want it to go any page.
These are my Database Columns

You cant save using a method without a route with only PHP.
If you want to do this, take a look on livewire component, who allow you to use Javascript with PHP.
But you need to few understand Javascript.
I propose you to create a route with a name and just point it to the method
Here in web.php
Route::post('/post-form', [YourController::class, 'addSchool'])->name('addschool');
Then after in your view
<form action="{{route('addschool')}}" method="post">
#csrf
<div class="form-group">
<h3 style="color: #000000" for="escola">Nome da Escola</h3>
<input type="text" id="escola" name="escola" class="form-control"/>
</div>
<div>
<button type="submit" class="btn btn-danger">Registar Escola</button>
</div>
</form>

You can do that by using ajax call from the front-end using on click event attach to button. it will dynamically send the request to your specified controller method and you can display the response(data) in the front-end specified place without page loading
for example take a look at the given code
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$(".btn-submit").click(function(e){
e.preventDefault();
var escola = $("input[name=escola]").val();
$.ajax({
type:'POST',
url:'{{route('addschool')}}',
data:{name:escola},
success:function(data){
alert(data.success);
//add your login here for the response
}
});
});

Related

how to make a multipage form

i'm making a website for online exams. i made 1 question per page and i made a custom pagination but now i dont know how to make when i move to the next question i save the answer of the previous question so i can submit all the answers to the databse
this is the view code
<form method="POST" action="{{route("answer.store")}}">
#csrf
<div class="content" v-for="question in questions">
<div v-if="post.qtype === 'choose'">
<div class="font-weight-bold p-4"> #{{question.qname}}</div>
<div v-for="choice in question.choices">
<div class="p-4">
<input type="radio" class="form-check-input" style="display: block" id="radio" :name="'answers[q' + post.id + '][]'" :value="choice">
<label class="form-check-label" for="radio">#{{choice}}</label>
</div>
</div>
</div>
</div>
{{ Form::hidden('exam_id', Crypt::encrypt($exam->id)) }}
<input class='btn btn-primary' v-if="pagination.current_page == pagination.last_page" id='submit-btn' type="submit">
</form>
expected result : all the answers get submited
actual result : only last answer get submited
**Note: im using default laravel pagination but i use json scripts and axios to move throw pagination without refreshing page **
If I understood correctly (and you are also using Vue.js for frontend), I suggest using one of the 2 following approaches:
Use Vuex - Create 1 big json object that will be filled after submitting every step and finally, send it via axios to your API
Have 1 parent component to hold the big object in its data and child component which will represent current step of the multi-step form. Each child step should validate its inputs and then emit the data to parent component. After coming to the last step, just send the request from the parent.
Bonus: I strongly recommend taking a look at https://v2.vuejs.org/v2/guide/components-dynamic-async.html for child components with keep alive tag in case you want to be able to get to previous step as well.
General architecture for the second approach (I didn't test it but you should get the big picture):
// Parent.vue
<template>
<div>
<keep-alive>
<component v-bind:is="actualStep" #stepSubmitted="handleStepSubmitted"></component>
</keep-alive>
</div>
</template>
<script>
export default {
components: {
Step1: () => import("./Step1"),
Step2: () => import("./Step2")
},
data() {
return {
resultToSend: [],
formSteps: ["Step1", "Step2"],
actualStep: "Step1"
};
},
methods: {
handleStepSubmitted(dataFromStep) {
resultToSend.push(dataFromStep);
if (formSteps.indexOf(actualStep) === formSteps.length - 1) {
this.submitData();
} else {
this.actualStep = this.nextStep();
}
},
nextStep() {
return this.formSteps[this.formSteps.indexOf(actualStep) + 1];
},
submitData() {
// send your post request
}
}
};
</script>
// Step1.vue
<template>
<div>
<input v-model="data1" type="text" />
<button #click="submitstep">Next</button>
</div>
</template>
<script>
export default {
data() {
return {
data1: ""
};
},
methods: {
submitStep() {
this.$emit("stepSubmitted", data1);
}
}
};
</script>
// Step2.vue
<template>
<div>
<input v-model="data2" type="text" />
<button #click="submitstep">Next</button>
</div>
</template>
<script>
export default {
data() {
return {
data2: ""
};
},
methods: {
submitStep() {
this.$emit("stepSubmitted", data2);
}
}
};
</script>
You have to create an array with a key-value pair then write a method that pushes the ids and answers into the array on every page change(If a user wants to turn back and change the question then you need to implement CRUD actions for this array). If the user achieved the last page then post your array into your database with axios.
Use JavaScript to submit the form when the next button is clicked:
var nextBtn = document.getElementById("nextBtn");
nextBtn.addEventListener("click", function(e){
e.preventDefault();
let form = document.getElementById("form");
form.submit();
return true;
});

JQuery Ajax post method is not working in laravel

I want to save an image and two text field using JQuery,Ajax. here, i'm using bootstrap modal. But when I submit the modal form it's show MethodNotAllowedHttpException Exception.
My Ajax Method.
$(document).ready(function(){
$('#advisoradd').on('submit',function(){
var name=$('#adname').val();
var title=$('#adtitle').val();
var img=$('#adfile').val();
$.ajax({
url:"{{route('add.advisor')}}",
type:'post',
data:{
'_token':"{{csrf_token()}}",
'name':name,
'title':title,
'img':img,
},
success:function(data)
{
console.log(data);
}
});
});
});
My view Modal code.
<form method="POST" enctype="multipart/form-data">
{{csrf_field()}}
<div class="form-group">
<div class="img_upload_team">
<button class="btn">+</button>
<input type="file" name="myfile" id="adfile">
</div>
<h2>Add A Profile Photo</h2>
<p>Click “+” Sign to Add</p>
</div>
<div class="form-group">
<input type="text" name="adname" class="form-control" id="adname" placeholder="Name">
</div>
<div class="form-group">
<input type="text" name="adtitle" class="form-control" id="adtitle" placeholder="Title">
</div>
<button type="submit" class="btn btn_modal_submit" id="advisoradd">Add</button>
</form>
My controller and Route for this Request.
public function addadvisor(Request $request)
{
$advisor=new Advisor();
$advisor->name=$request->name;
$advisor->title=$request->title;
$file = $request->file('img') ;
$fileName = $file->getClientOriginalName();
$destinationpath=public_path().'/images/';
$file->move($destinationpath,$fileName);
$advisor->image=$fileName;
$advisor->save();
return response()->json($advisor);
}
Route::post('/advisor','ImageController#addadvisor')->name('add.advisor');
You've mixed up button and form events. Buttons don't have a submit event, forms do. Since you're adding the event on the button, change it to click.
We should also add a preventDefault() to stop the button from submitting the form.
(We could also add the type="button" attribute on the button element to stop it from submitting the form).
This should work:
$(document).ready(function() {
// Add a 'click' event instead of an invalid 'submit' event.
$('#advisoradd').on('click', function(e) {
// Prevent the button from submitting the form
e.preventDefault();
// The rest of your code
});
});

Controller not getting inputs laravel

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

Using Ajax Request with PHPUnit and Laravel testing

I am doing tests in Laravel with phpunit. I run a test that inserts that into a textbox and press a button. Then, theres an Ajax Post that sends the info to the server and returns the response. If I return a string has the following code, in the test I should get that string correct?
I have the following controller:
class MyController extends Controller{
public static function createNewComplaintStep_2(){
return "error";
}
}
The route:
Route::post('/createNewComplaint_Step2', 'MyController#createNewComplaintStep_2');
The view with form and ajax method:
<form id="formToSubmit" data-value="createNewComplaint_Step2" class="form-horizontal">
{!! csrf_field() !!}
<div class="form-group">
<label class="col-md-4 control-label">Customer:</label>
<div class="col-md-3">
<input class="form-control" name="customer_name" required>
</div>
</div>
<button type="submit" class="btn btn-success" name="subBTN"\>
</form>
(...)
<script>
$( '#formToSubmit' ).on( 'submit', function(e) {
var href = $(this).data('value');
e.preventDefault();
$.ajax({
type: "POST",
url: href,
data: $(this).serialize(),
success: function( msg ) {
$("#container-fluid").html(msg);
$('.se-pre-con').hide();
}
});
});
</script>
The phpunit test:
$this->visit('/createNew')
->type('NAME', 'customer_name')
->press('subBTN')
->see('error');
Is there something wrong? Because if I run the code, I get error
Failed asserting that the page contains the HTML [error]. Please check the content above
The content above is the view that is above. It seems that the ajax request is not working with phpunit.
Any suggestions??
thanks in advance!
You are working with jquery Ajax, which is a client side scripting language, basically executed in the browser at runtime it cannot be used by Laravel in tests.
Here your Ajax is not even execute so how can you get the string that's why this error is coming.
But you can try some extensions/drivers for laravel that can enable this feature.
Just check out Selenium:-
https://laracasts.com/discuss/channels/testing/has-anyone-tried-laravel-integrated-package-in-laravel-52

Reload data without refreshing the page using Ajax and Twig

I have a page where a user can write a comment and post it by a simple form.
I'm trying, without success, to do this with ajax using twig.
I can send the ajax request to my controller without problem and the comment is saved in my database.
My issue is to reload a part of my twig template without refreshing the whole page.
The return of my controller:
return $app['twig']->render('#views_suivi/suivi_affaire.html.twig', array('cache' => false,
'auto_reload' => true,
'affaire' => $affaire,
'comments' => $comments
));
$comments countains all the comments of an article. When I send an ajax request, my table comment is updated. Is there a way to update the variable $comments and re-send it to my twig without refreshing the whole page?
Edit: sorry, here's the code of my controller (it just insert a comment in my db)
function addCommentAjax(Application $app, Request $request)
{
$cmt = new CommentaireQueries($app);
$postParams = $app["request"]->request->all();
//var_dump($postParams);
if(isset($postParams['files'])) unset($postParams['files']);
return !empty($postParams) ? $cmt->insertCommentAffaire($app,$postParams) : false;
}
Ajax: 'AjoutCommentaire' is the route to my controller addCommentAjax
$(document).ready(function() {
$('form').on('submit',function(e){
e.preventDefault();
$.ajax({
type : "POST",
url : "AjoutCommentaire",
data: $(this).serialize(),
success : function() {
alert('success');
}
});
});
});
My form:
<form role="form" method="POST">
<div class="form-group">
<textarea class="summernote" id="contents" rows="10" name="comment"></textarea>
</div>
<input type="hidden" name="phase" value="1" />
<input type="hidden" name="id_affaire" value="{{ affaire.id }}" />
<center><button type="submit" class="btn btn-link btn-block">Envoyer</button></center>
</form>
Basically, I just want to add a comment without refreshing the page.
Thank you !
url in ajax request is not defined properly. You can't just specify route name, you should generate url by route:
$.ajax({
type: "POST",
url: "path('AjoutCommentaire', {})",
...

Categories