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
},
Related
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
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.
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
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
I'm a bit confused how to access file data using with angular from a basic form. I'm following a tut on: (https://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs) and youtube (https://www.youtube.com/watch?v=vLHgpOG1cW4). They seem to get it right but when I try things seem to go a different way. Anyways here's my HTML form:
<form>
<div class="form-group">
<label for="name">Full Name</label>
<input type="text" ng-model="customer.name" id="name" class="form-control"/>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" ng-model="customer.email" id="name" class="form-control"/>
</div>
<div class="form-group">
<label for="file">Image</label>
<input type="file" file-model="customer.file" id="file" class="form-control"/>
</div>
<div class="form-group">
<button type="submit" ng-click="submit()" class="btn btn-primary">Submit</button>
</div>
</form>
And the Directive
app.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
And finally the controller:
app.controller('CustomerController', ['$scope','CustomerService', function($scope, CustomerService){
$scope.customer = {};
CustomerService.save($scope.customer);
}]);
When I {{ customer }} in my view I'm getting something like this:
{"name":"Robert DeNiro","email":"robie#godfather.com","file":{}}
It's that empty last "file":{} file object that's causing me problems getting values to post to server.
Here's my Customer Service code:
var CustomerService = function($resource) {
return $resource('advertisements/:id', { id: '#_id' }, {
update: {
method: 'PUT' // this method issues a PUT request
},
save: {
method: 'post',
transformRequest: angular.identity,
'Content-Type': undefined
}
});
};
CustomerService.$inject = ['$resource'];
app.service('CustomerService', CustomerService);
I'm using Laravel 5.1 and its reporting validation errors 'required' on all fields suggesting there's an empty object sent through. Thanks in advance.
I have added a submit() method in CustomerController like this:
$scope.submit = function(){
var file = $scope.customer.file;
console.log('file is ' );
console.log(file.name);
console.log($scope.customer.file);
console.dir($scope.customer.file);
};
And in there you can see I've tried experimenting with console.log() and console.dir() and i seem to get the results. For example if i console.log($scope.customer) or console.dir($scope.customer) it gives me the nested file object with all file details. And its looking like this:
> Object {name: "robert deniro", email: "robie#godfather.com", file: File}
> Object
Notice file: File Therefore I'm able to access the file contents/object within the submit() like this: console.log(file.name) or console.log(file.type) or console.log(file.size). I don't know why I was missing it all this time. I hope someone learn from my mistake.
May be that form requires the attribute enctype="multipart/form-data".