Vue / Laravel - Axios post multiple field - laravel

I created a component that can add additional fields by pressing a button. I don't know how would I submit this in the database with axios.post and laravel controller. I was able to achieve it in the past with the use of jquery and pure laravel, but I'm confused how to implement it in vue and axios.
Component.vue
<template>
<v-app>
<table class="table">
<thead>
<tr>
<td><strong>Title</strong></td>
<td><strong>Description</strong></td>
<td><strong>File</strong></td>
<td></td>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in rows" :key="row.id">
<td><v-text-field outlined v-model="row.title" /></td>
<td><v-text-field outlined v-model="row.description" /></td>
<td>
<label class="fileContainer">
<input type="file" #change="setFilename($event, row)" :id="index">
</label>
</td>
<td><a #click="removeElement(index);" style="cursor: pointer">X</a></td>
</tr>
</tbody>
</table>
<div>
<v-btn #click="addRow()">Add row</v-btn>
<v-btn class="success" #click="save()">Save</v-btn>
<pre>{{ rows | json}}</pre>
</div>
</v-app>
</template>
<script>
export default {
data: ()=> ({
rows: []
}),
methods: {
addRow() {
var elem = document.createElement('tr');
this.rows.push({
title: "",
description: "",
file: {
name: 'Choose File'
}
});
},
removeElement(index) {
this.rows.splice(index, 1);
},
setFilename(event, row) {
var file = event.target.files[0];
row.file = file
},
save() {
// axios.post
}
}
}
</script>
Controller.php
public function store(Request $request)
{
// store function
}

save() {
let data = this.rows
axios
.post("Url", {
data
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err)
});
}
ref link https://github.com/axios/axios

save() {
axios
.post("/your/uri", {
user_id: 1,
user_name:'jhone doe',
email:'test#test.com'
})
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error)
});
}
You can retrieve your data from your controller $request->user_id,...,$request->email
Tip: if you post any object,you must JSON.stringify(your_json) them and in a response data from controller json_decode($your_json,true) or you need to modify your header file.
Always use '/your/uri' instead of /your/uri/ without trailing '/'

It now works. I'll be posting my code just in case someone encounter the same hurdle. Than you very much to #kamlesh-paul and #md-amirozzaman
Component.vue
<script>
export default {
data: ()=> ({
rows: [],
}),
methods: {
addRow() {
this.rows.push({
corporate_objective_id: '',
kpa: '',
kpi: '',
weight: '',
score: '',
equal: '',
file: {
name: 'Choose File'
}
});
},
removeElement(index) {
this.rows.splice(index, 1);
},
setFilename(event, row) {
var file = event.target.files[0];
row.file = file
},
save() {
const postData = {
data: this.rows
}
console.log(postData)
axios
.post('/api/employee-objective', {postData})
.then(res => { console.log(res) })
.catch(err => { console.log(err) });
}
}
}
</script>
Controller.php
public function store(Request $request) {
foreach($request->data as $data) {
$container = EmployeeObjective::updateOrCreate([
'kpa_info' => $data['kpa'],
'kpi_info' => $data['kpi'],
'kpa_weight' => $data['weight'],
'kpa_score_1' => $data['score'],
'kpa_equal' => $data['equal'],
]);
$container->save();
}
}

Related

Obtain values from Laravel Controller and display in Vue

In a Laravel 8 view, I have a Vue component with a form.
<contact-form-component contact-store-route="{{ route('contact.store') }}">
</contact-form-component>
ContactFormController.vue
<template>
<div>
<div v-if="success">
SUCCESS!
</div>
<div v-if="error">
ERROR!
</div>
<div v-show="!success">
<form
#submit.prevent="storeContact"
method="POST"
novalidate="novalidate"
#keydown="clearError"
>
<input type="text" name="fullname" v-model="formData.fullname" />
<input type="text" name="email" v-model="formData.email" />
<input type="text" name="phone" v-model="formData.phone"/>
<button type="submit">Submit</button>
</form>
</div>
</template>
<script>
import Form from "./Form.vue";
export default {
mixins: [Form],
props: {
contactStoreRoute: String,
},
data() {
return {
formData: {
fullname: null,
lname: null,
email: null,
phone: null,
message: null,
},
};
},
methods: {
storeContact() {
this.post(this.contactStoreRoute, this.formData);
},
},
mounted() {},
};
</script>
Form.vue
<template></template>
<script>
import FormErrors from "./FormErrors.vue";
export default {
name: "Form",
mixins: [FormErrors],
data() {
return {
success: false,
error: false,
errorMessage: "",
};
},
methods: {
post(url, data) {
this.success = false;
this.error = false;
axios
.post(url, data)
.then((res) => {
this.onSuccess(res.data.message);
})
.catch((error) => {
if (error.response.status == 422) {
this.setErrors(error.response.data.errors);
} else {
this.onFailure(error.response.data.message);
}
});
},
get(url, data) {
this.success = false;
this.error = false;
axios
.get(url, data)
.then((res) => {
this.onSuccess(res.data.message);
})
.catch((error) => {
if (error.response.status == 422) {
this.setErrors(error.response.data.errors);
} else {
this.onFailure(error.response.data.message);
}
});
},
onSuccess(message) {
this.reset();
this.success = true;
},
onFailure(message) {
this.error = true;
this.errorMessage = message;
},
reset() {
this.clearAllErrors();
for (let field in this.formData) {
this.formData[field] = null;
}
},
},
};
</script>
FormErrors.vue
<template></template>
<script>
export default {
name: "FormErrors",
data() {
return {
errors: {},
};
},
methods: {
setErrors(errors) {
this.errors = errors;
},
hasError(fieldName) {
return fieldName in this.errors;
},
getError(fieldName) {
return this.errors[fieldName][0];
},
clearError(event) {
Vue.delete(this.errors, event.target.name);
},
clearAllErrors() {
this.errors = {};
},
},
computed: {
hasAnyError() {
return Object.keys(this.errors).length > 0;
},
},
};
</script>
When the form is submitted, a laravel post route is called and the information is stored in the database.
Route::post('/contact/store', [ContactController::class,'store'])->name('contact.store');
After this, the Vue component now hides the form and displays a "success" message. So far, everything works great.
Now, I would like to add a step. Instead of success message, I want to obtain the last id entered in the db and show a new form with a hidden field last_id. I am unsure of how to obtain this information from the controller.
It would be a continuation of the previous form, but I do not want to gather all the data at once, I want it in steps. Now, it is also important to gather data from the first form, and if the user quits after the first form that is fine, no problem, but if the user continues with the second form I need to "link" it to the previous form through the last_id.
I think that I am not approaching this problem correctly, maybe I need to change the logic of what I am doing.
Adding last_id to ContactController return:
class ContactController extends Controller
{
public function store(Request $request)
{
$data = $request->validate([
'fullname' => 'required',
'email' => 'required|email',
'phone' => 'required',
]);
$contact_form = Contact::create($data);
$last_id = $contact_form->id;
return [
//how do I "send" this to the Vue component?
'last_id' => $last_id
];
}
}
This would be the "second step" form using the last ID. It would have it's own post route.
<h4>Your form has been successfully submitted, now please give us more info that will be linked to the previous form:</h4>
<form>
<input type="hidden" name="last_id" value="{HOW_TO_GET_THE_LAST_ID_HERE?}" />
<textarea name="message" required></textarea>
<input type="submit" value="Submit" />
</form>
You can use a JSON response:
https://laravel.com/docs/9.x/responses#json-responses
You can return the id in your Controller for example like this:
return response()
->json(['last_id' => $last_id])
You will be able to get the value from the response object of the post call
.then((res) => {
//get the id from the response
this.last_id = (res.data.last_id);
})

How to manipulate axios returned data to print in desired formate

<template>
<div>
<table class="table table-responsive">
<tbody>
<tr v-for="(gameresults, index) in gameresults" :key="index">
<td style="color: #082ad4; font-size: 24px;">{{ gameresults.game_name }}</br>
<h3 style="color:#00d2f1; font-size: 18px;">{{ gameresults.cards }}</h3></td>
<h3 style="color:#00d2f1; font-size: 18px;">{{ this.formattedArray }}</h3></td>
</tr>
</tbody>
</table>
</div></template>
<script>
export default {
props: [''],
mounted() {
console.log('Component mounted.')
},
data() {
return {
gameresults:0,
};
},
methods: {
changeResult() {
let formattedArray = [];
this.gameresults.cards.forEach(str => {
const subs = str.split('');
const subsTwo = subs[2].split(',');
const formattedString = `${subs[1]} - ${subs[0]}-${subsTwo[0]}${subs[4]}-${subsTwo[1]}`;
formattedArray.push(formattedString);
});
console.log('Formatted Data', formattedArray);
}
// this.gameresults[0].cards
},
computed: {
chkgameresults() {
axios.post('/gameresults')
.then(response => {
this.gameresults = response.data ;
this.changeResult();
});
},
},
created () {
this.chkgameresults();
}
};
</script>
ref code axios fetches mysql concat data in array format having 2 keys [game_name and card ] i want card key to be manipulated . when i print card array using this.gameresults[0].card its giving me 123-9,897-0 using {{ gameresults.cards }} inside vu template , i want value to get manipulated like 123-90-897 ( only last 0 gets before the second exp and become 0-897 removing ',' separator
Assuming that your data is an array lets define a method...........
formatData(myData) {
let formattedArray = [];
myData.myValue.forEach(str => {
const subs = str.split('');
const subsTwo = subs[2].split(',');
const formattedString = `${subs[1]} - ${subs[0]}-${subsTwo[0]}${subs[4]}-${subsTwo[1]}`;
formattedArray.push(formattedString);
});
console.log('Formatted Data', formattedArray);
}

data not stored in laravel back end from axios post of vue js front end

I have some data that i need to store in my database coming from localStorage. One is an input field where a user can change the quantity of an item, the other is a radio box where the user has to select an address to deliver to. The issue is that it just won't store the address_id in my database nor update the qty field of the input in my cart. Could someone take a look at it and explain why this doesn't work? I'd appreciate it so much thanks!
Note: The data object is reactive, I checked in my vue dev tools and it changes the data correclty so no issue there.
Vue add to cart button component:
<template>
<form #submit.prevent="addToCart">
<button>Add to cart</button>
</form>
</template>
<script>
export default {
props: ['productId', 'categoryId'],
data() {
return {
product: {},
cart: []
}
},
methods: {
fetchData() {
axios.get(`http://localhost:8000/api/product/${this.productId}/category/${this.categoryId}`)
.then(res => {
const { product } = res.data;
this.product.id = product.id
this.product.title = product.title;
this.product.fitSize = product.fit_size;
this.product.jeansSize = product.jeans_size;
this.product.price = product.price;
this.product.img = product.images[0].images;
this.product.quantity = 1;
})
.catch(err => console.log(err))
},
addToCart() {
if(localStorage.getItem('cart')) {
// Little note to myself:
// Grab data from local storage and turn it into a js array of objects
// Push new product to that array every time the addToCart method gets fired
// get that array with the additional items and store back in local storage as a JSON string
let cart = JSON.parse(localStorage.getItem('cart'));
cart.push(this.product)
return localStorage.setItem('cart', JSON.stringify(cart))
} else {
this.cart.push(this.product)
localStorage.setItem('cart', JSON.stringify(this.cart))
}
}
},
mounted() {
this.fetchData()
}
}
</script>
Vue checkout component:
<template>
<div>
<div v-for="product in products" v-bind:key="product.id">
<p>Img: {{product.img}}</p>
<p>Title: {{product.title}}</p>
<p>Price: {{product.price}}</p>
<input v-model="product.quantity" type="number" name="qty" id="qty">
<br>
</div>
<form method="POST" #submit.prevent="placeOrder">
<div v-for="address in user.addresses" v-bind:key="address.id">
<input type="radio" v-model="addressId" v-bind:value="address.id" name="address_id" id="address_id">{{address.street}}
</div>
<button>Place order</button>
</form>
</div>
</template>
<script>
export default {
props: ['user'],
data() {
return {
products: null,
addressId: null,
orders: [],
}
},
methods: {
fetchDataFromLocalStorage() {
this.products = JSON.parse(localStorage.getItem('cart'))
},
createOrders() {
this.products.forEach(product => {
this.orders.push({
qty: product.quantity,
user_id: this.user.id,
product_id: product.id,
address_id: this.addressId
})
})
},
placeOrder() {
const sendOrders = { orders: this.orders }
axios.post(`http://localhost:8000/api/user/${this.user.id}/checkout`, sendOrders)
.then(res => console.log(res.data))
.catch(err => console.log(err))
},
},
mounted() {
this.fetchDataFromLocalStorage();
this.createOrders();
}
}
</script>
Laravel store method:
public function store(Request $request, $id)
{
foreach ($request->orders as $order) {
Order::create([
'qty' => $order['qty'],
'product_id' => $order['product_id'],
'user_id' => $order['user_id'],
'address_id' => $order['address_id']
]);
}
return response()->json('Order created');
}
Order model:
class Order extends Model
{
protected $guarded = [];
public function product()
{
return $this->hasOne(Product::class);
}
public function user()
{
return $this->belongsTo(Order::class);
}
public function addresses()
{
return $this->hasOne(Addresses::class);
}
}
Laravel api route:
Route::post('/user/{id}/checkout', 'CheckoutController#store');
Tinker when I make a post request:
App\Order {#3072
id: "127",
qty: "1", // Default value just won't change whenever I try to update it!
delivered: "0",
product_id: "3", // This works
created_at: "2019-12-23 10:08:09",
updated_at: "2019-12-23 10:08:09",
user_id: "1", // This works
address_id: null, // This doesn't
},
],

Vue / Laravel - Dynamic multiple form saving data

I have a dynamic form that successfully adds multiple field by a click of the button. My problem comes when saving the data in the database. I want to be able to save in the employee_id field the id of the Auth::user.
This is my current set of code. Should I use a different approach such as for loop instead of foreach?
Component.vue
<tr v-for="(row, index) in rows" :key="row.id">
<td><base-select
:items="department_objectives"
item-text="department_objective"
item-value="id"
label="Department Objectives"
/></td>
<td><v-textarea label="KPA" placeholder=" " class="mr-2" rows="1" outlined v-model="row.kpa" /></td>
<td><v-textarea label="KPI" placeholder=" " class="mr-2" rows="1" outlined v-model="row.kpi" /></td>
<td><v-text-field label="Weight" placeholder=" " class="mr-2" outlined v-model="row.weight" /></td>
<td><v-text-field label="Score" placeholder=" " class="mr-2" outlined :disabled="disabled" filled v-model="row.score" /></td>
<td><a #click="removeElement(index);" style="cursor: pointer">Remove</a></td>
</tr>
addRow () {
this.rows.push({
kpa: '',
kpi: '',
weight: '',
score: '',
equal: '',
});
save () {
axios
.post('/api/employee-objective', { data: this.rows })
.then(res => { console.log(res) })
.catch(err => { console.log(err) });
}
Controller.php
public function store(Request $request) {
foreach($request->data as $data) {
$container = EmployeeObjective::updateOrCreate([
'employee_id' => // insert ID
'kpa_info' => $data['kpa'],
'kpi_info' => $data['kpi'],
'kpa_weight' => $data['weight'],
'kpa_score_1' => $data['score'],
'kpa_equal' => $data['equal'],
]);
$container->save();
}
}
It's fine using foreach as long all data you want is available like the key
to put the id of authenticated user in employee_id just put this one
Auth::id();
and put it above your code
use Auth;
I managed to make it work, somehow this syntax works. Hopefully someone could enlighten me more about this.
Controller.php
public function store(Request $request)
// This works
foreach($request->rows as $data) {
$test = new EmployeeObjective;
$test->employee_id = $request->id;
$test->kpa_info = $data['kpa'];
$test->save();
// This does not work
foreach($request->rows as $data) {
EmployeeObjective::updateOrCreate([
'employee_id' => $request->id,
'kpa_info' => $data['kpa'],
Now here is the tricky part. I saved the data from the $store to my local object and passed it during the save method.
Component.vue
created () {
this.auth = this.$store.state.authUser.id
},
save () {
axios.post('/api/employee-objective', {
rows: this.rows,
id: this.auth
})
.then(res => { console.log(res) })
.catch(err => { console.log(err) });
}

Vue js can't display data

My data from api I want to display is not working
[{"gameID":1368656,"gameReultTime":"2019-03-01 01:08:25","gameReult":2763.33,"totalPayout":1.98,"totalbet":100}]
display and there is no any data
<tr v-for="data in dataresults">
<td>{{data.gameID}}</td>
<td> {{ data.totalbet }}</td>
<td>{{data.gameReult}}</td>
<td>{{data.totalPayout}}</td>
</tr>
JS
data() {
return {
dataresults: [],
};
},
axios
.get("api/getoutcome")
.then((response) => {
this.dataresults = response.data
})
.catch(function(error) {
console.warn(error);
});
Please try to move your code for example to mounted lifecycle hook:
data() {
return {
dataresults: [],
};
},
mounted() {
axios
.get("api/getoutcome")
.then((response) => {
this.dataresults = response.data
})
.catch(function(error) {
console.warn(error);
});
}

Resources