Vue.js not updating URL correctly - php

Join.vue
<template>
<div class="container join-form">
<form>
<div class="container">
<h2>Join to session</h2>
</div>
<div class="form-group">
<label for="sessionId">Session ID:</label>
<input v-model="sessionId" class="form-control" type="text" name="sessionId" placeholder="Session ID">
</div>
<div class="form-group">
<label for="userName">Username:</label>
<input v-model="userName" class="form-control" type="text" name="userName" placeholder="Your name">
</div>
<button v-on:click.prevent="joinSession()" class="btn btn-primary">Join session</button>
</form>
</div>
</template>
<script>
export default {
data() {
return {
userName: "",
sessionId: this.$route.params.sessionId,
userId: null
};
},
methods: {
joinSession() {
this.$http
.post('/joinsession', {
userName: this.userName,
sessionId: this.sessionId
})
.then(
data => {
this.userId = data.body.userId;
this.$router.push("/user/" + this.sessionId + "/" + this.userId);
},
() => {
this.$router.push("/error");
}
);
}
}
};
</script>
<style>
.join-form {
width: 50%;
}
</style>
I wanna have "/user/{sessionId}/{userId}" but instead I've got
"http://projectx.laragon:8090/user/3/[object%20Object],[object%20Object]"
How can I solve this issue? I am using Laravel in combination with Vue-Resource &% Vue-Router in order to switch between different .vue files that are all together in an App.vue. This means my URL is not actively entered, it is just displayed without fetching from the server.
eg: "user/{userId}/{sessionId}" is a 404 if I didn't register it in my web.php

It seems you actually want do
this.$router.push( { path: '/user', params: { sessionId: this.sessionId, userId: this.userId } });
If it still not work, check your route configuration and sessionId / userId values.
For more info, see the docs

Related

Submitting a form via Fetch API in Laravel

I've been trying to submit the form via a Fetch API, but having no luck so far. I can submit the form without one, but for this exercise it has to be with Fetch.
Form
<form action="{{ url('/process')}}" method="POST">
#csrf
<div class="form-container">
<div class="form-item">
<label for="name">Full Name<span class="required">*</span></label>
<input type="text" name="name" id="name" placeholder="Enter your name" />
</div>
<div class="form-item">
<label for="email">Email<span class="required">*</span></label>
<input type="email" name="email" id="email" placeholder="Enter your email address" required />
</div>
</div>
<div class="form-container">
<button type="submit">Submit</button>
</div>
</form>
^This submits successfully as is, but again I need to use Fetch.
Fetch API:
form.addEventListener("submit", (e) => {
e.preventDefault();
const csrfToken = document.querySelector("input[name='_token']").value;
fetch("success.blade.php", {
method: "post",
body: JSON.stringify(process),
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": csrfToken,
},
})
.then((response) => {
console.log(response);
return response.text();
})
.then((text) => {
return console.log(text);
})
.catch((error) => console.error(error));
}
Routes
Route::get('/', [ContactController::class, 'create']);
Route::get('/all', [ContactController::class, 'getAll']);
Route::post('/process', [ContactController::class, 'store']);
ContactController.php
public function store(Request $request)
{
$contact = Contact::create($request->input());
$message = 'Thank you for your message! We will review your submission and respond to you in 24-48 hours.';
if ($request->ajax()) {
return response()->json(compact('message'));
}
return view('success');
}
success.blade.php is a file I created to display that thank you message, but something tells me I don't need it if I'm using this function store right.
If I remove action="{{ URL('/process') }} , and just use the Fetch API, then I get this error:
The POST method is not supported for this route. Supported methods: GET, HEAD.
you should not send fetch request to the blade
you must send request to controller
change url of fetch with controller

Error of "Invalid argument supplied for foreach()" in Laravel

This is my blade view where i am taking values of total closing report and total deposit. if it differs, automatically difference is being calculated and displayed. On the basis of difference, below details need to be added for the difference amount and stored in cashoutexpense.
For example - Total Closing Report is 200 , Total Deposit is 100 then details need to be provided for difference amount. i.e 100. In this case, suppose user has given input for expense amount as 50 in one textbox and 50 in another by adding another row.
<div class="form-group row">
<div class="col-12">
<label>Total Closing Report</label>
<input class="form-control" v-model="form.closing_report_total" #change="calculate" type="number" required name="closing_report_total" placeholder="Enter Closing Report Total">
</div>
</div>
<div class="form-group row">
<div class="col-12">
<label>Total Deposit</label>
<input class="form-control" type="number" v-model="form.total_deposit" #change="calculate" required name="total_deposit" placeholder="Enter Total Deposit">
</div>
</div>
<div class="form-group row">
<div class="col-12">
<label>Difference</label>
<input class="form-control" type="number" v-model="form.difference" name="difference" placeholder="Enter Difference" readonly>
</div>
</div>
<div class="form-group row" v-if="form.difference != 0" v-for="(comment, k) in form.cashoutexpenses" :key="k">
<div class="col-4">
<input type="text" class="flatpickr form-control" v-model="comment.expense_date" required name="expense_date" placeholder="Click here to choose Date">
</div>
<div class="col-4">
<input class="form-control" type="number" v-model="comment.amount" required name="amount" placeholder="Enter Expense Amount" #change="calculate_error">
</div>
<div class="col-4">
<input class="form-control" type="text" v-model="comment.comment" required name="comment" placeholder="Enter Expense Comments">
</div>
<div class="col-4">
<button class="btn btn-sm btn-danger" type="button" #click="removeRow(k)">Remove</button>
</div>
</div>
<div class="form-group row" v-if="form.left > 0">
<div class="col-12">
<input class="btn btn-primary form-control" type="button" value="Add Row" #click="addRow()">
</div>
</div>
Below is my script code for the same.
<script>
var app = new Vue({
el: '#app',
mounted: function() {
},
computed: {
difference: function() {
return this.form.difference = this.form.closing_report_total - this.form.total_deposit;
}
},
data: {
form: {
closing_report_total : 0.00,
total_deposit: 0.00,
difference: 0.00,
left: 0.00,
comments: '',
cashoutexpenses: [],
buffer: []
},
},
methods: {
addRow() {
this.form.cashoutexpenses.push({
date: '',
amount: '',
comment: '',
});
this.form.buffer = JSON.parse(JSON.stringify(this.form.cashoutexpenses));
},
removeRow(index) {
this.form.cashoutexpenses.splice(index, 1);
this.form.buffer = JSON.parse(JSON.stringify(this.form.cashoutexpenses));
},
calculate: function() {
this.form.difference = this.form.closing_report_total - this.form.total_deposit;
this.form.cashoutexpenses = [];
this.form.buffer = JSON.parse(JSON.stringify(this.form.cashoutexpenses));
if(this.form.difference != 0) {
this.addRow();
}
},
calculate_error: function() {
this.form.left = this.form.difference - this.form.cashoutexpenses.reduce((a,b)=> (a + (parseInt(b['amount'])||0)),0);
if(this.form.left<0) {
alert("Sum of expenses should not exceed total amount");
for(var i=0; i<this.form.cashoutexpenses.length;i++) {
if(this.form.cashoutexpenses[i].amount!=this.form.buffer[i].amount) {
this.form.buffer[i].amount = 0;
this.form.cashoutexpenses[i].amount=this.form.difference - this.form.buffer.reduce((a,b)=> (a + (parseInt(b['amount'])||0)),0);
}
}
}
else if(this.form.left>0) {
alert("Please add "+this.form.left+" more");
}
this.form.buffer = JSON.parse(JSON.stringify(this.form.cashoutexpenses));
},
formSubmit: function(e) {
e.preventDefault();
let currentObj = this;
// let data = new FormData();
let formData = new FormData()
formData.append('closing_report_total', this.form.closing_report_total);
formData.append('total_deposit', this.form.total_deposit);
formData.append('difference', this.form.difference);
formData.append('form.cashoutexpenses', this.form.cashoutexpenses);
let config = { headers: { 'Content-Type': 'multipart/form-data' } }
axios.post('/cashoutdetails/store', formData ,config)
.then(response => {
//console.log(formData);
//alert('data saved');
//window.location.href = "{{ route('cashoutdetails.index')}}";
})
.catch(function (error) {
alert('Error');
});
}
}
})
</script>
if i check for the same in vue plugin of mozilla firefox, correct data is being displayed which is as follows --
cashoutexpenses:Array[2]
0:Object
amount:"50"
comment:"test2"
date:""
expense_date:"2021-10-10"
1:Object
amount:"50"
comment:"test3"
date:""
expense_date:"2021-10-12"
Now in my controller , i am fetching the data which is as below -
$comments = $request->form_cashoutexpenses;
//return $comments;
foreach($comments as $c) {
return $c;
$cashout_comments = new CashOutExpenses;
$cashout_comments->cashout_id = $cashout_details->id;
$cashout_comments->expense_date = $c['expense_date'];
$cashout_comments->amount = $c['amount'];
$cashout_comments->explanation = $c['comment'];
$cashout_comments->save();
}
return response()->json([
'message' => 'Details added!',
], 201);
If i return $comments, it gives reply as [object Object],[object Object] otherwise it returns error for foreach.
if i return $request->all(); ... it gives following output -
{"closing_report_total":"200","total_deposit":"100","difference":"100","form.cashoutexpenses":"[object Object]"}
Please help me to save this data in cashout_expense table.
I do not fully understand your code, but I've noticed some potentially problematic parts:
$request->form_cashoutexpenses most likely is not an array, that is why you probably getting this error. You can check it putting dd($comments, gettype($comments)); after declaration of $comments and rerunning page
Having return statement inside foreach loop at the first line seems to be silly, because the code below will never be executed.

How to validate recaptcha with Laravel and Vue.js?

RESOLVED : see changes in repository, in vue component, controller, new RUle Recaptcha, and blade file : https://github.com/IllichOulianov/m1_serveur_projet
I want to include a recaptcha in a comment form, using this package https://github.com/DanSnow/vue-recaptcha/ . It is correctly displayed under the input fields, the recaptcha behaves correctly when clicked, but I always get a 422 response in the console after verifying recaptcha and submitting :
POST http://localhost:8000/comments 422 (Unprocessable Entity)
dispatchXhrRequest # app.js:285
xhrAdapter # app.js:119
dispatchRequest # app.js:724
Promise.then (async)
request # app.js:531
Axios.(anonymous function) # app.js:551
wrap # app.js:984
submit # app.js:1851
submit # app.js:36913
invokeWithErrorHandling # app.js:40775
invoker # app.js:41100
original._wrapper # app.js:46453
and this response in the devtools network tab :
{"message":"The given data was invalid.","errors":{"g-recaptcha-response": > ["The g-recaptcha-response field is required."]}}
I tried some things but none worked. I guess the trouble lies in the html element, the script fields and/or the validation rules. What do I need to add/modify ?
My codes, and repository if needed : https://github.com/IllichOulianov/m1_serveur_projet
CommentForm.vue :
<template>
<div>
<form #submit.prevent="submit">
<div class="form-group">
<input type="text" class="form-control" placeholder="Votre nom" name="name" id="name" v-model="fields.name" />
<div v-if="errors && errors.name" class="text-danger">{{ errors.name[0] }}</div>
</div>
<div class="form-group">
<input type="email" class="form-control" placeholder="Votre e-mail" name="email" id="email" v-model="fields.email" />
<div v-if="errors && errors.email" class="text-danger">{{ errors.email[0] }}</div>
</div>
<div class="form-group">
<textarea class="form-control" placeholder="Votre commentaire" id="content" name="content" rows="5" v-model="fields.content"></textarea>
<div v-if="errors && errors.content" class="text-danger">{{ errors.content[0] }}</div>
</div>
<div class="form-group">
<vue-recaptcha sitekey="XXXXX"></vue-recaptcha>
<div v-if="errors && errors.recaptcha" class="text-danger">{{ errors.recaptcha[0] }}</div>
</div>
<button type="submit" class="btn btn-primary">Publier le commentaire (après modération)</button>
</form>
</div>
</template>
<script>
import VueRecaptcha from 'vue-recaptcha';
export default {
components:{VueRecaptcha},
data() {
return {
fields: {
name:'',
email:'',
content:'',
article_id:window.article_id,
},
errors: {},
}
},
methods: {
submit() {
this.errors = {};
axios.post('/comments', this.fields).then(response => {
alert('Message sent!');
}).catch(error => {
if (error.response.status === 422) {
this.errors = error.response.data.errors || {};
}
});
},
},
}
</script>
COmmentCOntroller
public function store(Request $request,CommentsRepositoryInterface $interface) {
$this->validate($request, [
'name'=>'bail|required|min:3|alpha_num',
'email'=>'bail|required|email',
'content'=>'bail|required|between:3,5000',
'g-recaptcha-response'=>'required|recaptcha'
]);
$interface->save($request);
return response()->json(null, 200);
}
IN my blade file:
<script src="https://www.google.com/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit" async defer>
</script>
<script type="text/javascript">article_id={{$article->id}};</script>
[...]
<div id="app">
<comment-form></comment-form>
</div>
<script src={{asset("js/app.js")}}></script>
Thanks !

window.location.href will not redirect at all

When I log in using my Ajax login form, it shows an error instead of redirecting to the dashboard with:
window.location.href = "https://my.distincttrack.com/admin/";
If I refresh the page it will redirect me to the dashboard because of the auth guard in the laravel middleware. But the code I posted above is not at all redirecting me to that page when the response is a success.
I tried changing it to window.location but that did not help. I took out the double quotes and that did not work so I put them back. I tried turning off ajax and seeing what a normal form HTTP submit would respond and it echoed success as it should have.
My Jquery Ajax Code:
return {
init: function () {
l(), $("#m_login_signin_submit").click(function (e) {
e.preventDefault();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
var a = $(this), l = $(this).closest("form");
l.validate({
rules: {
email: {required: !0, email: !0},
password: {required: !0}
}
}), l.valid() && (a.addClass("m-loader m-loader--right m-loader--light").attr("disabled", !0), l.ajaxSubmit({
url: "",
method: "post",
data: {
email:jQuery('#email').val(),
password:jQuery('#password').val()
},
success: function (response) {
if(response==="success") {
window.location.href="https://my.distincttrack.com/admin/";
} else {
setTimeout(function () {
a.removeClass("m-loader m-loader--right m-loader--light").attr("disabled", !1), i(l, "danger", "Incorrect username or password. Please try again.")
}, 2e3);
}
}
}))
}),
My controller where the user is logged and a response is made:
public function store(Request $request)
{
if (Auth::guard('system')->attempt(['email' => $request['email'], 'password' => $request['password'], 'status' => 1], $request['remember'])) {
return 'success';
}
return 'failed';
}
My HTML View in the blade:
<form class="m-login__form m-form" action="" method="post">
#csrf
<div class="form-group m-form__group">
<input class="form-control m-input" type="email" placeholder="Email" name="email" autocomplete="off" required>
</div>
<div class="form-group m-form__group">
<input class="form-control m-input m-login__form-input--last" type="password" placeholder="Password" name="password" required>
</div>
<div class="row m-login__form-sub">
<div class="col m--align-left m-login__form-left">
<label class="m-checkbox m-checkbox--light">
<input type="checkbox" name="remember"> Remember me
<span></span>
</label>
</div>
<div class="col m--align-right m-login__form-right">
Forget Password ?
</div>
</div>
<div class="m-login__form-action">
<button id="m_login_signin_submit" class="btn btn-focus m-btn m-btn--pill m-btn--custom m-btn--air m-login__btn">Sign In</button>
</div>
</form>
And my meta tag with the CSRF token is correct.
When I log in and the ajax receives the response 'success' it's supposed to automatically redirect the user to the dashboard. When it fails it will flip the else statement and show an error ("Incorrect Credentials......") and so forth.
Temporarily you can see my issue until I cannot provide public access:
https://my.distincttrack.com/admin/login
email: jarrod#distincttrack.com
pass: admin

Laravel VueJS Axios send array to controller

I have a laravel 5.4 application which uses VueJS 2.0 for the front end.
I'm trying to post the visitors array to the controller after populating on the page but when I return the array from the controller the data isn't there.
I can't see for the life of me what I'm doing wrong? What's interesting is if I send two visitors through I get two empty arrays returning from my controller so the number of visitors is working it's just not capturing the data.
My vue instance.
<script>
new Vue({
el: '#app',
data: {
visitors: [],
visitor: [],
},
methods: {
addVisitor() {
this.visitors.push(this.visitor);
this.visitor = [];
},
storeVisit()
{
axios({
method: 'post',
url: '/visit/new',
data: {
visitors: this.visitors
}
});
}
},
});
</script>
My HTML page
<p>Visitors</p>
<div class="columns">
<div class="column">
<input class="input" placeholder="First Name" v-model="visitor.first">
</div>
<div class="column">
<input class="input" placeholder="Last Name" v-model="visitor.last">
</div>
<div class="column">
<input class="input" placeholder="Company" v-model="visitor.company">
</div>
<div class="column">
<input class="input" placeholder="Email" v-model="visitor.email">
</div>
<div class="column">
<button class="button is-primary" #click="addVisitor()">Add</button>
</div>
</div>
I've then got a button that actions the storeVisit() method.
<button class="button is-primary" #click="storeVisit">Save Visit</button>
My controller waiting the post request
public function store(Request $request)
{
return $request->visitors;
}
My response
{"visitors":[[],[]]}
visitor should be an object, not an array
data: {
visitors: [],
visitor: {}, // <- object here
},
addVisitor() {
this.visitors.push(this.visitor);
this.visitor = {}; // <- reset to an empty object
},

Categories