pass result ajax to blade with foreach - ajax

i am trying to pass the ajax response to my view and use it as a variable to foreach,I need it to update the quantity of bikes available on the dates selected by the user
the procedure I use is:
I take the selected data in the calendar, I pass them via ajax to my controller
from the controller I execute the queries on the database and return to ajax a json with the data.
the ajax data must be cycled to assign the corresponding quantities to the categories but I don't know how to pass this data to the view
my view
#foreach ($category as $cat)
<div class="col pb-5 m-1">
<?php
$categoryId=DB::table('categories')->select('id')->orderBy('id', 'asc')->get();
foreach ($categoryId as $key) {
$quantity[$key->id]=DB::table('bikes')->where('category_id','=',$key->id)->count('*');
}
?>
<div class="card cat m-auto position-relative " id="cat{{$cat->id}}" >
#foreach ($qty as $item=>$val)
#if ($item==$cat->id)
<p class="m-3" id="numberqty" style="font-weight: bold;color:#ce2e30;text-shadow: 2px 5px 3px rgba(150, 150, 150, 0.92);">{{-- x{{$val}} --}}</p>
#endif
#endforeach
<p class="check position-absolute" style="display: none"><i class="fa fa-check" aria-hidden="true"></i></p>
<input class="cat-id" type="number" value="{{$cat->id}}" hidden>
<input class="id-cat" type="checkbox" name="category[]" id="category" value="{{$cat->id}}" hidden>
<img class="card-img-top p-3" src="{{asset('storage/'.$cat->cover_image)}}" alt="">
<div class="card-body my-n3">
<h3 class="card-title text-center" style="text-shadow: 2px 5px 3px rgba(150, 150, 150, 0.92);">{{$cat->tipo}}</h3>
{{-- <h3 class="card-title">Disponibilità: {{$val}}</h3> --}}
<button class="btn btn-primary pl-5 pr-5 ml-5 drop" type="button">{{__('payment.page.price')}}</button>
<button class="btn btn-primary pl-5 pr-5" type="button">Dettagli</button>
<div class="show-drop" style="display: none">
<h3 class="text-center my-1">{{__('payment.page.price')}}</h3>
<p class="text-center"> {{__('payment.page.1day')}} {{$cat->base}} </p> <hr>
<p class="text-center"> {{__('payment.page.2day')}} {{$cat->twoDay}}</p> <hr>
<p class="text-center"> {{__('payment.page.3day')}} {{$cat->threeDay}}</p> <hr>
<p class="text-center"> {{__('payment.page.4day')}} {{$cat->fourDay}}</p> <hr>
<p class="text-center"> {{__('payment.page.5day')}} {{$cat->fiveDay}}</p> <hr>
<p class="text-center"> {{__('payment.page.6day')}} {{$cat->sixDay}}</p> <hr>
<p class="text-center"> {{__('payment.page.7day')}} {{$cat->sevenDay}}</p>
<p class="text-center"> {{$cat->overprice}} {{__('payment.page.overprice')}}</p>
{{-- <p>{{$cat->overprice}}</p> --}}
</div>
</div>
</div>
<div class="number-drop" style="display: none">
<label for="quantity{{$cat->id}}">Nome</label>
<input name="{{$cat->id}}" type="number" id="quantity{{$cat->id}}" class="form-control" value="0" >
</div>
</div>
#endforeach
my ajax
$('#range_date').on('change', function(){
var data = $(this).val();
var split = data.split(' - ');
var startDate = split[0];
var dayStart = startDate.substr(0,2);
var monthStart = startDate.substr(3,2);
var yearStart = startDate.substr(6,4);
var startCorrect = monthStart+"/"+dayStart+"/"+yearStart;
console.log(startCorrect);
var endDate = split[1];
var dayEnd = endDate.substr(0,2);
var monthEnd = endDate.substr(3,2);
var yearEnd = endDate.substr(6,4);
var endCorrect = monthEnd+"/"+dayEnd+"/"+yearEnd;
console.log(endCorrect);
var date1 = new Date(startCorrect);
var date2 = new Date(endCorrect);
var diffTime = Math.abs(date2 - date1);
var diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
$.ajax({
"url": "bookingCheck",
"data": {
"start": startCorrect,
"end":endCorrect
},
"method": "GET",
success: function (response) {
let res = response;
let qty = res['qty'];
console.log(qty);
document.getElementById('numberqty').innerHTML=qty;
$('#numberqty').html(qty.html);
}
});
});
my controller
public function checkBike(Request $request){
$date1=Carbon::parse($request->start)->format('Y-m-d');
$date2=Carbon::parse($request->end)->format('Y-m-d');
$contract=DB::table('contracts')->get();
$contractdate=DB::table('contracts')->whereRaw('? between data_inizio and data_fine', [$date1,$date2])->get();
if (count($contractdate) > 0) {
foreach ($contractdate as $key) {
$id=$key->id;
}
$bikeContract=DB::table('bike_contract')->where('contract_id','=',$id)->get();
foreach ($bikeContract as $key) {
$bikeselect[$key->id]=DB::table('bikes')->where('id','=',$key->bike_id)->get();
}
foreach ($bikeselect[$key->id] as $key) {
$idcat=$key->category_id;
$quantity=DB::table('bikes')->select('category_id')->whereNotIn('category_id',[$idcat])->get();
}
foreach ($quantity as $key) {
$qty[$key->category_id]=DB::table('bikes')->where('category_id','=',$key->category_id)->count('*');
}
return response()->json(["qty"=>$qty]);
} else {
$categoryId=DB::table('categories')->select('id')->orderBy('id', 'asc')->get();
foreach ($categoryId as $key) {
$quantity[$key->id]=DB::table('bikes')->where('category_id','=',$key->id)->count('*');
}
return response()->json(["qty"=>$quantity]);
}
}
}

Try this:
success: function (response) {
response = JSON.parse(response);
let qty = response.qty;
}

Related

Laravel Ajax Add To Cart Not working 500 internal error

I have code I am working on. I will list the page, the route, and the controller code. When I inspect and click on the add to cart button I get 500 internal server error and I cannot figure out what I did. It should be giving a message checking to see if the item is already in the cart and if not send a message saying item is in the cart but I can't get past the 500 internal server error.
Page
#extends('layouts.frontend.frontend')
#section('title')
Distinctly Mine - {{$products->name}}
#endsection
#section('content')
<div class="py-3 mb-4 shadow-sm babyblue border-top">
<div class="container">
<h6 class="mb-0">Collections / {{$products->category->name}} / {{$products->name}}</h6>
</div>
</div>
<div class="container">
<div class="card-shadow shadow-sm product_data">
<div class="card-body">
<div class="row">
<div class="col-md-4 border-right">
<div class="img-hover-zoom img-hover-zoom--xyz card-img-top">
<img src="{{ asset('backend/uploads/products/'.$products->image) }}" class="w-100 h-100" alt="{{$products->name}}">
</div>
</div>
<div class="col-md-8">
<h2 class="mb-0">{{ $products->name}}</h2>
<hr>
<label for="" class="me-3">Price: ${{$products->original_price}}</label>
<p class="mt-3">{!! $products->small_description !!}</p>
<hr>
#if($products->qty > 0)
<label for="" class="badge bg-success text-dark fw-bold">In Stock</label>
#else
<label for="" class="badge bg-danger text dark fw-bold">Out of Stock</label>
#endif
<div class="row mt-2">
<div class="col-md-2">
<input type="hidden" value="{{$products->id}}" class="prod_id">
<label for="Quantity">Quantity</label>
<div class="input-group text-center mb-3" style="width:130px">
<button type="button" class="input-group-text decrement-btn">-</button>
<input type="text" name="quantity" value="1" class="form-control qty-input" />
<button type="button" class="input-group-text increment-btn">+</button>
</div>
</div>
<div class="col-md-10">
<br />
<button type="button" class="btn btn-warning text-dark fw-bold ms-3 float-start"><i class=" me-1 fa fa-heart text-danger me-1"></i>Add To Wishlist</button>
<button type="button" class="btn btn-success ms-3 float-start text-dark fw-bold addToCartBtn"><i class="me-1 fa fa-shopping-cart text-dark me-1"></i>Add to Cart</button>
</div>
<hr>
<h2>Description</h2>
{{$products->description}}
</div>
</div>
</div>
</div>
</div>
</div>
#endsection
#section('scripts')
<script>
$(document).ready(function (){
$('.addToCartBtn').click(function (e){
e.preventDefault();
var product_id = $(this).closest('.product_data').find('.prod_id').val();
var product_qty = $(this).closest('.product_data').find('.qty-input').val();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
method: "POST",
url: "/add-to-cart",
data: {
'product_id': product_id,
'product_qty': product_qty,
},
dataType: "dataType",
success: function (response){
alert(response.status);
}
});
});
$('.increment-btn').click(function (e){
e.preventDefault();
var inc_value = $('.qty-input').val();
var value = parseInt(inc_value,10);
value = isNaN(value) ? 0 :value;
if(value < 10)
{
value++;
$('.qty-input').val(value);
}
});
$('.decrement-btn').click(function (e){
e.preventDefault();
var dec_value = $('.qty-input').val();
var value = parseInt(dec_value,10);
value = isNaN(value) ? 0 :value;
if(value > 1)
{
value--;
$('.qty-input').val(value);
}
});
});
</script>
#endsection
Route
Route::middleware(['auth'])->group(function (){
Route::post('/add-to-cart',[CartController::class,'addProduct']);
});
Controller
<?php
namespace App\Http\Controllers\Frontend;
use App\Models\Product;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
class CartController extends Controller
{
public function addProduct(Request $request)
{
$product_id = $request->input('product_id');
$product_qty = $request->input('product_qty');
if(Auth::check())
{
$prod_check = Product::where('id',$product_id)->first();
if($prod_check)
{
if(Cart::where('prod_id',$product_id)->where('user_id',Auth::id())->exists())
{
return response()->json(['status' => $prod_check->name." Already Added to cart"]);
}else{
$cartItem = new Cart();
$cartItem->prod_id = $product_id;
$cartItem->user_id = Auth::id();
$cartItem->prod_qty = $product_qty;
$cartItem->save();
return response()->json(['status'=>$prod_check->name." Added to cart"]);
}
}
}
else{
return response()->json(['status'=> "Login To Continue"]);
}
}
}

How to save state of page even after reloading or closing the browser?

I am working on a quiz application using laravel as backend and vuejs to render the questions on the frontend. The thing that is confusing me how to store the state of quiz even after candidate reloads the page or he/she accidentally close the browser. I am thinking about saving the quiz progress in the database. Is there any better approach than this?
<template>
<div>
<div class="container quiz-steps" v-for="(question,index) in questions" v-bind:key="index">
<div v-show="index === currentIndex && timer>0">
<div>
<span class="badge badge-danger">{{ minutes }}</span>
<span class="badge badge-danger">{{ seconds }}</span>
</div>
<div class="progress">
<div class="progress-bar bg-danger" role="progressbar" :style="{width: returnTimerWidth()}" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<br>
<div class="container-quiz-question-pills">
<ul class="nav nav-pills quiz-question-pills">
<li> {{ wrong }}<i class="icon-remove"></i></li>
<li> {{ right }} <i class="icon-ok"></i></li>
</ul>
</div>
<div class="question-content">
<p>{{ question.question }}</p>
<!-- Material unchecked -->
<div class="form-check">
<input type="radio" v-model="picked" class="form-check-input" value="1" id="radio1" name="materialExampleRadios">
<label class="form-check-label" for="radio1">{{ question.option1 }}</label>
</div>
<!-- Material checked -->
<div class="form-check">
<input type="radio" v-model="picked" class="form-check-input" value="2" id="radio2" name="materialExampleRadios">
<label class="form-check-label" for="radio2">{{ question.option2 }}</label>
</div>
<div class="form-check">
<input type="radio" v-model="picked" class="form-check-input" value="3" id="radio3" name="materialExampleRadios">
<label class="form-check-label" for="radio3">{{ question.option3 }}</label>
</div>
<div class="form-check">
<input type="radio" v-model="picked" class="form-check-input" value="3" id="radio4" name="materialExampleRadios">
<label class="form-check-label" for="radio4">{{ question.option4 }}</label>
</div>
enter code here
</div>
<br><br><br><br>
<div>
<span> {{index+1}} / {{questions.length}} </span>
<button type="button" class="btn btn-outline-danger float-right btn-next" #click="nextQuestion(question.isCorrect)">Next</button>
</div>
<br>
<div class="progress">
<div class="progress-bar bg-danger" role="progressbar" :style="{width: returnWidth(index)}" aria-valuenow="100" aria-valuemin=0 aria-valuemax="100"></div>
</div>
</div>
</div>
<div v-if="currentIndex === questions.length || timer==0">
<div class="container thankyou-quiz-page">
<div class="text-center">
<p>Thnakyou for taking the Quiz!</p>
<br>
<div class="thankyou-msg">
<p>You have answered <span>{{ right }}</span> correct answers out of <span>{{ questions.length }}</span>. Your total time was <span>{{ minutesTaken }}:{{ secondsTaken }}</span>. The answers were sent to the administrator and he will contact you shortly.</p>
<p>Your total marks are {{ calculateScore() }}</p>
</div>
<br><br>
<div class="text-center quiz-choice">
Retake the Quiz<br>
Next Quiz
</div>
</div>
<br><br>
<div class="thankyou-message-button">
<button type="button" class="btn ">Retake the Quiz</button>
<button type="button" class="btn float-right ">Next Quiz</button>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
name:'TEST',
props:['quizId'],
data(){
return{
currentIndex:0,
picked:'',
right:0,
wrong:0,
questions:[
],
timer:0,
total:0,
minutes:0,
seconds:0,
minutesTaken:0,
secondsTaken:0,
remainingTime:0,
done:false,
interval: '',
negative: 0,
totalMarks: 0,
type: 0
}
},
methods:{
nextQuestion:function(e){
if(this.picked){
if(e==this.picked){
this.right++;
}
else{
this.wrong++;
}
}
this.currentIndex++;
if(this.currentIndex == this.questions.length){
this.timer = 0;
}
this.picked = '';
},
returnWidth(e){
if( e==0 ){
return 0+'%';
}
else {
return e / this.questions.length * 100+'%';
}
},
returnTimerWidth(){
if( this.remainingTime == 0 )
{
return 0+'%';
}
else{
return this.remainingTime / this.total * 100 + '%';
}
},
loadQuestions(){
axios.get("http://192.168.1.3:8000/api/quiz/"+this.quizId).
then( ({ data }) => ( this.questions = data.data.questions,
this.timer = data.data.timeAllowed * 60,
this.total = this.timer,
this.negative = data.data.negativePercentage,
this.getTime(this)
) )
},
getTime(){
let interval = setInterval( () => {
this.minutes = parseInt(this.timer / 60, 10);
this.seconds = parseInt(this.timer % 60, 10);
this.minutes = this.minutes < 10 ? "0" + this.minutes : this.minutes;
this.seconds = this.seconds < 10 ? "0" + this.seconds : this.seconds;
if (--this.timer <0 ) {
// this.timer = 0;
this.totalTime();
clearInterval(interval);
}
else{
this.remainingTime++;
this.returnTimerWidth();
}
}, 1000);
},
totalTime(){
this.minutesTaken = parseInt(this.remainingTime / 60, 10);
this.secondsTaken = parseInt(this.remainingTime % 60, 10);
this.minutesTaken = this.minutesTaken < 10 ? "0" + this.minutesTaken : this.minutesTaken;
this.secondsTaken = this.secondsTaken < 10 ? "0" + this.secondsTaken : this.secondsTaken;
},
calculateScore(){
this.totalMarks = this.right - ( this.wrong * this.negative );
// if(this.type==1){
// axios.post('http://192.168.1.3:8000/api/quizMarks', {
// Marks: this.totalMarks
// })
// .then(function (response) {
// console.log(response);
// })
// .catch(function () {
// // console.log(error);
// });
//
// }
// else if(this.type==0){
// axios.post('http://192.168.1.3:8000/api/quizMarks', {
// Marks: this.totalMarks
// })
// .then(function (response) {
// console.log(response);
// })
// .catch(function () {
// // console.log(error);
// });
// }
return this.totalMarks;
}
},
created() {
this.loadQuestions();
}
}
</script>
One way is to use local storage and check if the key exists once the page is loaded.
A cleaner way is to use vuex https://vuex.vuejs.org/ and a local storage plugin such as vuex persist.

laravel vuejs/axios put request Formdata is empty

I have a few application, when I am sending formdata using axios post data is successfully sent to API. but when i am using put request its not working with formData.
<template>
<div class="container">
<div class="container-fluid" style="background:#fff">
<div class="page-header">
<h4 class="page-title">
<i class="flaticon-users"></i> Leads
</h4>
<ul class="breadcrumbs">
<li class="nav-home">
<a href="/">
<i class="flaticon-home"></i>
</a>
</li>
<li class="separator">
<i class="flaticon-right-arrow"></i>
</li>
<li class="nav-item">
<router-link to="/leads">Leads</router-link>
</li>
<li class="separator">
<i class="flaticon-right-arrow"></i>
</li>
</ul>
</div>
<template>
<div class="btn-wrapper">
<button v-on:click="seen = !seen" class="btn btn-primary btn-md">
<i class="flaticon-interface-1"></i>Add New Lead
</button>
</div>
<p></p>
</template>
<div class="row">
<div class="col-md-12" v-if="!seen">
<div class="card">
<div class="card-header">
<h4 class="card-title">
<i class="flaticon-interface-1"></i> New Leads
</h4>
</div>
<div class="card-body">
<form
#submit.prevent="addLeads"
id="leadform"
class="mb-3"
enctype="multipart/form-data"
>
<div class="col-md-12">
<div class="row">
<div class="col-md-6">
<label>Lead</label>
<div class="form-group">
<input
type="text"
id="name"
name="lead_name"
class="form-control"
placeholder="Lead Name"
v-model="form.name"
>
<template v-if="errors">
<span v-for="(fieldsError, fieldName) in errors" :key="fieldName">
<template v-if="fieldName == 'name'">
<p class="errors">
<strong>{{ fieldsError.join('\n') }}</strong>
</p>
</template>
</span>
</template>
</div>
</div>
<div class="col-md-6">
<label>Source</label>
<div class="form-group">
<textarea
type="text"
id="source"
name="source"
class="form-control"
placeholder="lead Souve"
v-model="form.source"
></textarea>
<template v-if="errors">
<span v-for="(fieldsError, fieldName) in errors" :key="fieldName">
<template v-if="fieldName == 'source'">
<p class="errors">
<strong>{{ fieldsError.join('\n') }}</strong>
</p>
</template>
</span>
</template>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<label>Value</label>
<div class="form-group">
<input
type="text"
id="value"
name="value"
class="form-control"
placeholder="lead Value"
v-model="form.value"
>
<template v-if="errors">
<span v-for="(fieldsError, fieldName) in errors" :key="fieldName">
<template v-if="fieldName == 'value'">
<p class="errors">
<strong>{{ fieldsError.join('\n') }}</strong>
</p>
</template>
</span>
</template>
</div>
</div>
<div class="col-md-6">
<label>Notes</label>
<div class="form-group">
<textarea
type="text"
id="notes"
name="notes"
class="form-control"
placeholder="lead Notes"
v-model="form.notes"
></textarea>
<template v-if="errors">
<span v-for="(fieldsError, fieldName) in errors" :key="fieldName">
<template v-if="fieldName == 'notes'">
<p class="errors">
<strong>{{ fieldsError.join('\n') }}</strong>
</p>
</template>
</span>
</template>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="exampleFormControlSelect1">Assigned To</label>
<template v-if="!userlist">
<select class="form-control" id="assigned_to">
<option value>No User Found</option>
</select>
</template>
<template v-else>
<select
v-model="form.assigned_to"
name="assigned_to"
class="form-control"
id="assigned_to"
>
<option value>Please Select</option>
<option v-for="user in userlist" :key="user.id" :value="user.id">
<template v-if="user.id == currentUser.id">Me</template>
<template v-else>{{ user.name }}</template>
</option>
</select>
</template>
<template v-if="errors">
<span v-for="(fieldsError, fieldName) in errors" :key="fieldName">
<template v-if="fieldName == 'assigned_to'">
<p class="errors">
<strong>{{ fieldsError.join('\n') }}</strong>
</p>
</template>
</span>
</template>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label>Close Date</label>
<div class="clearfix"></div>
<date-picker v-model="form.date" name="close_date"></date-picker>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<label>Email</label>
<div class="form-group">
<input
type="text"
id="email"
name="email"
class="form-control"
placeholder="User Email"
v-model="form.email"
>
<template v-if="errors">
<span v-for="(fieldsError, fieldName) in errors" :key="fieldName">
<template v-if="fieldName == 'email'">
<p class="errors">
<strong>{{ fieldsError.join('\n') }}</strong>
</p>
</template>
</span>
</template>
</div>
</div>
<div class="col-md-6">
<label>Phone</label>
<div class="form-group">
<input
type="text"
id="phone"
name="phone"
class="form-control"
placeholder="User Phone Number"
v-model="form.phone"
>
<template v-if="errors">
<span v-for="(fieldsError, fieldName) in errors" :key="fieldName">
<template v-if="fieldName == 'phone'">
<p class="errors">
<strong>{{ fieldsError.join('\n') }}</strong>
</p>
</template>
</span>
</template>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<input
type="file"
multiple="multiple"
id="attachments"
#change="uploadFieldChange"
>
<hr>
<div class="col-md-12">
<div
class="attachment-holder animated fadeIn"
v-cloak
v-for="(attachment, index) in attachments"
>
<template v-if="attachment.file_name">
<span class="label label-primary">{{ attachment.file_name}}</span>
</template>
<template v-else>
<span
class="label label-primary"
>{{ attachment.name + ' (' + Number((attachment.size / 1024 / 1024).toFixed(1)) + 'MB)'}}</span>
</template>
<span
class
style="background: red; cursor: pointer;"
#click="removeAttachment(attachment)"
>
<button class="btn btn-xs btn-danger">Remove</button>
</span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-check">
<label>Status</label>
<br>
<label class="form-radio-label">
<input
class="form-radio-input"
v-model="form.status"
type="radio"
name="status"
value="open"
checked
>
<span class="form-radio-sign">Open</span>
</label>
<label class="form-radio-label ml-3">
<input
class="form-radio-input"
v-model="form.status"
type="radio"
name="status"
value="sent"
>
<span class="form-radio-sign">Proposal Sent</span>
</label>
<label class="form-radio-label ml-3">
<input
class="form-radio-input"
v-model="form.status"
type="radio"
name="status"
value="won"
>
<span class="form-radio-sign">Won</span>
</label>
<label class="form-radio-label ml-3">
<input
class="form-radio-input"
v-model="form.status"
type="radio"
name="status"
value="lost"
>
<span class="form-radio-sign">lost</span>
</label>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<button type="submit" class="btn btn-success">Save</button>
<button #click="clearForm()" class="btn btn-danger">Cancel</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<div class="container-fluid" style="background:#fff;">
<kanban-board :stages="stages" :blocks="blocks" #update-block="updateBlock">
<div v-for="stage in stages" :slot="stage">
<h2>{{ stage }}</h2>
</div>
<div v-for="block in blocks" :slot="block.id">
<div>
<strong>{{ block.name }}</strong>
</div>
<p></p>
<button class="btn btn-danger">UKDH</button>
<button class="btn btn-warning">£ {{ block.value }}</button>
<router-link :to="`/account/${block.id}/convert`" class="btn btn-primary">create account</router-link>
<div class="text-right">
<router-link :to="`/leads/${block.id}`" class="btn btn-link btn-info">
<i class="la la-street-view"></i>
</router-link>
<a href="#" #click="deleteLead(block.id)" class="btn btn-link btn-danger">
<i class="la la-times"></i>
</a>
<a href="#" #click="editLead(block)" class="btn btn-link btn-primary">
<i class="la la-edit"></i>
</a>
</div>
</div>
</kanban-board>
</div>
</div>
</template>
<script>
import { addLeadsAPI } from "../../helpers/api";
import { updateStatus } from "../../helpers/api";
import { getCommonAPI } from "../../helpers/api";
import { deleteAPI } from "../../helpers/api";
import validate from "validate.js";
import DatePicker from "vue2-datepicker";
export default {
name: "leads",
components: {
DatePicker
},
data() {
return {
leads: [],
userlist: [],
attachments: [],
percentCompleted: 0,
upload_size: 0,
result: {},
stages: ["open", "sent", "lost", "won"],
blocks: [],
form: {
id: "",
name: "",
source: "",
value: 0,
notes: "",
user_id: "",
assigned_to: 1,
date: new Date(),
email: "",
phone: "",
status: ""
},
lead_id: "",
pagination: {},
edit: false,
isOpen: 0,
seen: true,
errors: null
};
},
created() {
this.fetchLeads();
this.getusers();
},
mounted() {
this.$store.dispatch("leads");
},
methods: {
getusers(page_url) {
let vm = this;
getCommonAPI("/users", "get", {
headers: {
Authorization: `Bearer ${this.currentUser.token}`,
Accept: "application/json"
}
}).then(res => {
vm.userlist = res.data;
});
},
fetchLeads(page_url) {
let vm = this;
page_url = page_url || "/leads/lead";
getCommonAPI(page_url, "get", {
headers: {
Authorization: `Bearer ${this.currentUser.token}`,
Accept: "application/json"
}
}).then(res => {
vm.blocks = res.data.data;
//vm.makePagination(res.meta, res.links);
});
},
makePagination(meta, links) {
let pagination = {
current_page: meta.current_page,
last_page: meta.last_page,
next_page_url: links.next,
prev_page_url: links.prev
};
this.pagination = pagination;
},
editLead(form) {
console.log(form);
this.edit = true;
this.seen = false;
this.form.id = form.id;
this.form.name = form.name;
this.form.lead_sid = form.lead_sid;
this.form.status = form.status;
this.form.type = form.type;
this.form.source = form.source;
this.form.value = form.value;
this.form.notes = form.notes;
this.form.email = form.email;
this.form.phone = form.phone;
this.form.assigned_to = form.assigned_to;
this.form.date = form.close_date;
this.attachments = form.uploads;
},
clearForm() {
this.edit = false;
this.form.id = null;
this.form.user_id = null;
this.form.assigned_to = "";
this.form.type = "";
this.form.status = true;
this.form.name = "";
this.form.source = "";
this.form.value = "";
this.form.notes = "";
this.form.email = "";
this.form.phone = "";
this.attachments = [];
},
addLeads() {
if (this.edit === false) {
// add new leads
this.errors = null;
const constraints = this.getConstraints();
const errors = validate(this.$data.form, constraints);
if (errors) {
this.errors = errors;
return;
}
// multiple file uploading
this.lead = document.getElementById("leadform");
const formData = new FormData(this.lead);
if (this.attachments.length > 0) {
for (var i = 0; i < this.attachments.length; i++) {
let attachment = this.attachments[i];
formData.append("attachments[]", attachment);
}
}
var config = {
headers: { "Content-Type": "multipart/form-data" },
onUploadProgress: function(progressEvent) {
this.percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
this.$forceUpdate();
}.bind(this)
};
//end
this.$store.dispatch("lead");
addLeadsAPI(formData, "post").then(res => {
swal("Good job!", "You clicked the button!", "success");
this.clearForm();
this.fetchLeads();
//this.attachments = [];
});
} else {
this.errors = null;
const constraints = this.getConstraints();
const errors = validate(this.$data.form, constraints);
if (errors) {
this.errors = errors;
return;
}
console.log("i am in edit");
// multiple file uploading
this.lead = document.getElementById("leadform");
let formData = new FormData(this.lead);
if (this.attachments.length > 0) {
for (var i = 0; i < this.attachments.length; i++) {
let attachment = this.attachments[i];
formData.append("attachments[]", attachment);
}
}
console.log(formData);
var config = {
headers: { "Content-Type": "multipart/form-data" },
onUploadProgress: function(progressEvent) {
this.percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
this.$forceUpdate();
}.bind(this)
};
//end
console.log(formData);
this.$store.dispatch("lead");
//update
addLeadsAPI(formData, "put").then(res => {
swal("Good job!", "You clicked the button!", "success");
this.clearForm();
this.fetchLeads();
//this.attachments = [];
});
}
},
getConstraints() {
return {
name: {
presence: true,
length: {
minimum: 6,
message: "Must be at least 6 characters long"
}
},
source: {
presence: true,
length: {
minimum: 6,
message: "Must be at least 6 characters long"
}
},
value: {
presence: true,
length: {
minimum: 1,
message: "Must be at least 1 characters long"
}
},
notes: {
presence: true,
length: {
minimum: 6,
message: "Must be at least 6 characters long"
}
}
};
},
updateBlock(id, status) {
//api call axios
updateStatus(id, status, "get").then(res => {
this.clearForm();
this.fetchLeads();
});
this.blocks.find(b => b.id === Number(id)).status = status;
},
deleteLead(id) {
swal({
title: "Are you sure?",
text: "Do you really want to delete Lead!",
type: "warning",
buttons: {
confirm: {
text: "Yes, delete it!",
className: "btn btn-success"
},
cancel: {
visible: true,
className: "btn btn-danger"
}
}
}).then(Delete => {
if (Delete) {
deleteAPI(`/lead/${id}`, "delete", {
headers: {
Authorization: `Bearer ${this.currentUser.token}`,
Accept: "application/json"
}
}).then(res => {
swal({
title: "Deleted!",
text: "Your lead has been deleted.",
type: "success",
buttons: {
confirm: {
className: "btn btn-success"
}
}
});
this.fetchLeads();
});
} else {
this.fetchLeads();
swal.close();
}
});
},
getAttachmentSize() {
this.upload_size = 0; // Reset to beginningƒ
this.attachments.map(item => {
this.upload_size += parseInt(item.size);
});
this.upload_size = Number(this.upload_size.toFixed(1));
this.$forceUpdate();
},
removeAttachment(attachment) {
this.attachments.splice(this.attachments.indexOf(attachment), 1);
this.getAttachmentSize();
},
// This function will be called every time you add a file
uploadFieldChange(e) {
console.log(this.attachments);
var files = e.target.files || e.dataTransfer.files;
if (!files.length) return;
for (var i = files.length - 1; i >= 0; i--) {
this.attachments.push(files[i]);
}
console.log("out");
// Reset the form to avoid copying these files multiple times into this.attachments
document.getElementById("attachments").value = [];
}
},
computed: {
users() {
return this.$store.getters.users;
},
currentUser() {
return this.$store.getters.currentUser;
}
}
};
</script>
<style lang="scss">
#import "../assets/board.scss";
</style>
<style scoped>
.vue-js-switch#changed-font {
font-size: 30px;
}
.hide {
display: none;
}
.errors {
color: lightcoral;
border-radius: 5px;
padding: 21px 0 2px 0;
}
</style>
when edit option true. I am calling method addLeadsAPI for posting data with axios put but Formdata is empty $request->all().
Anyone can help me with this?seems axios put is not working for editing data. through formdata.
Laravel can not handle multipart-formdata well with PUT method. See Input from PUT requests sent as multipart/form-data is unavailable #13457.
If your code actually uses the PUT method, it seems to be affected by this problem.
There are several workarounds.
Dealing with the client side:
Instead of PUT method, use POST method with _method parameter value set to PUT (called 'method spoofing')
Dealing with the server side:
Add a package that performs multipart processing to Laravel. (ex. illuminatech/multipart-middleware)
Use pecl/apfd extension which provides ability to parse 'multipart/form-data' HTTP requests for any request method.
I have changed the axioscall into post and set the value _method:put
addLeads() {
if (this.edit === false) {
// add new leads
this.errors = null;
const constraints = this.getConstraints();
const errors = validate(this.$data.form, constraints);
if (errors) {
this.errors = errors;
return;
}
// multiple file uploading
this.lead = document.getElementById("leadform");
const formData = new FormData(this.lead);
if (this.attachments.length > 0) {
for (var i = 0; i < this.attachments.length; i++) {
let attachment = this.attachments[i];
formData.append("attachments[]", attachment);
}
}
var config = {
headers: { "Content-Type": "multipart/form-data" },
onUploadProgress: function(progressEvent) {
this.percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
this.$forceUpdate();
}.bind(this)
};
//end
this.$store.dispatch("lead");
formData.append("_method", "post");
addLeadsAPI(formData, "post", config).then(res => {
swal("Good job!", "You clicked the button!", "success");
this.clearForm();
this.fetchLeads();
//this.attachments = [];
});
} else {
this.errors = null;
const constraints = this.getConstraints();
const errors = validate(this.$data.form, constraints);
if (errors) {
this.errors = errors;
return;
}
console.log("i am in edit");
// multiple file uploading
this.lead = document.getElementById("leadform");
let formData = new FormData(this.lead);
if (this.attachments.length > 0) {
for (var i = 0; i < this.attachments.length; i++) {
let attachment = this.attachments[i];
formData.append("attachments[]", attachment);
}
}
formData.append("_method", "put");
formData.append("id", this.form.id);
console.log(formData);
var config = {
headers: { "Content-Type": "application/x-www-form-urlencoded" },
onUploadProgress: function(progressEvent) {
this.percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
this.$forceUpdate();
}.bind(this)
};
//end
console.log(formData);
this.$store.dispatch("lead");
//update
addLeadsAPI(formData, "put", config).then(res => {
swal("Good job!", "You clicked the button!", "success");
this.clearForm();
this.fetchLeads();
//this.attachments = [];
});
}
},
Well, I had an issue trying to update records using axios & vue.js.
The solution is to set the method value on the formData to putand send the request using the post method. Something like this:
console.log("i am in edit");
// multiple file uploading
this.lead = document.getElementById("leadform");
let formData = new FormData(this.lead);
if (this.attachments.length > 0) {
for (var i = 0; i < this.attachments.length; i++) {
let attachment = this.attachments[i];
formData.append("attachments[]", attachment);
}
}
formData.append("_method", "put");
console.log(formData);
In your axios request:
axios({
method: "POST", // this is important
url: {$your_destination_url},
data: formData,
headers: { "Content-Type": "multipart/form-data" }
})
.then(r => console.log(r.data))
.catch(e => console.log(e));
It may be related to this, https://laravel.com/docs/5.0/routing#method-spoofing.
when using PUT, PATCH or DELETE, you may need to also let laravel know the form method you are using. Try adding "_method" property with the value "PUT", and let me know if that works for you
My previous wrong code -
let data = new FormData()
data.append('message', 'AnyMessage')
Instead of FormData use the following String that works fine -
let data = "message=AnyMessage"

Why ajax calling for search doesn't display output?

I had search field using ajax call in laravel 5. It search in Db and display output in table. When user click on the page, it should display all db query. When user type in search field it should display the output according to the search input.
This is the controller for searching:
function action(Request $request)
{
if($request->ajax())
{
$output = '';
$query = $request->get('query');
if($query != '')
{
$data = DB::table('itemregistrations')
->where('name', 'like', '%'.$query.'%')
->paginate(10);
}
else
{
$data = DB::table('itemregistrations')
->paginate(10);
}
$total_row = $data->count();
if($total_row > 0)
{
foreach($data as $row)
{
$output .= '
<tr>
<td>'.$row->name.'</td>
<td>'.$row->seksyen_kecil.'</td>
<td>'.$row->nobadan.'</td>
</tr>
';
}
}
else
{
$output = '
<tr>
<td align="center" colspan="5">No Data Found</td>
</tr>
';
}
$data = array(
'table_data' => $output,
'total_data' => $total_row
);
echo json_encode($data);
}
}
This is the view blade displaying the output:
<div class="row">
<div class="form-group">
<div class="col-lg-5">
<input type="text" class="form-control" id="search" name="search"></input>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">Senarai Kakitangan</div>
<div class="panel-body">
#if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
#endif
#if(Auth::check())
<div class="container table-responsive col-lg-12">
<!-- <div class="container text-center"> -->
<h3 align="center">Total Data : <span id="total_records"></span></h3>
<table class="table table-striped table-bordered">
<thead>
<tr>
<td><strong>#</strong></td>
<td class="text-center col-lg-1"><strong>Nama</strong></td>
<td class="text-center col-lg-3"><strong>Seksyen</strong></td>
<td class="text-center col-lg3-2"><strong>No Badan</strong></td>
</tr>
</thead>
<tbody>
</tbody>
</table>
<!-- </div> -->
<ul class="pagination pull-right">
{{ $itemregistrations->links() }}
</ul>
</div>
#endif
#if(Auth::guest())
Anda perlu log masuk.
#endif
</div>
</div>
</div>
The javascript for searching:
<script>
$(document).ready(function(){
fetch_profil_data();
function fetch_profil_data(query = '')
{
$.ajax({
url:"{{ route('live_search.action') }}",
method:'GET',
data:{query:query},
dataType:'json',
success:function(data)
{
$('tbody').html(data.table_data);
$('#total_records').text(data.total_data);
}
})
}
$(document).on('keyup', '#search', function(){
var query = $(this).val();
fetch_profil_data(query);
});
});
</script>
The route for the search is:
Route::get('/profil/action', 'Modul\ProfilController#action')->name('live_search.action');
I couldn't find any error and console.log also doesn't produce any output..
The searching doesn't work and don't display any result.
The script link i put in app.blade.php
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
This is the error in log
C:\\xampp\\htdocs\\hre1m\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php(116): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter(Object(Illuminate\\Http\\Request))
#50 C:\\xampp\\htdocs\\hre1m\\public\\index.php(53):
Illuminate\\Foundation\\Http\\Kernel->handle(Object(Illuminate\\Http\\Request))
#51 C:\\xampp\\htdocs\\hre1m\\server.php(21):
require_once('C:\\\\xampp\\\\htdocs...')
#52 {main}
"}

Accessing variable parameters of Vuejs component inside a loop

I'm new to Vuejs. I have written a vuejs component for delete confirmation modal. I call this inside a list of records, here is my code :
<template id="bs-modal">
<div class="modal fade" id="confirmDeleteModal" tabindex="-1"
role="dialog" aria-labelledby="confirmDeleteModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close"
data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title"
id="confirmDeleteModalLabel">
Delete {{ item | capitalize }}
</h4>
</div>
<div class="modal-body">
Are you sure about deleting the {{ name }} {{ item }} ?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default"
data-dismiss="modal">No</button>
<button type="button" class="btn btn-primary"
v-on:click="deleteItem(id)">Yes</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
}
},
props: ['item', 'name', 'id'],
methods: {
deleteItem : function(id) {
var url = window.location.href;
var baseUrl = url.substring(0,
url.indexOf('/', url.indexOf('://') + 3) + 1);
var adminPosition = url.indexOf('admin/') + 6;
var entity = url.substring(adminPosition,
url.indexOf('/', adminPosition));
this.$http.delete(baseUrl + "admin/" + entity + "/" + id).then((response) => {
if (response.body.status_code == '200') {
// Calling just modal('hide') does not hide the backdrop
// There should be a better solution for this
$("#confirmDeleteModal").modal("hide");
$("#confirmDeleteModal").hide();
$('.modal-backdrop').hide();
$("body").removeClass("modal-open");
$("tr[data-id=" + id + "]").remove();
// Display success message
}
});
}
},
filters: {
capitalize: function (value) {
if (!value) {
return '';
}
value = value.toString();
return value.charAt(0).toUpperCase() + value.slice(1);
}
}
}
</script>
And here is my blade template where I call this component (I'm using laravel 5.3) :
#foreach ($categories as $category)
<tr data-id="{{ $category->id }}">
<td>{{ $category->id }}</td>
<td>{{ $category->name }}</td>
<td id="actions">
Show
Edit
Delete
<confirm-delete-modal item="category" id="{{ $category->id }}" name="{{ $category->name }}"></confirm-delete-modal>
</td>
</tr>
#endforeach
The parameters I pass to the component are variable and according to Vue devtools, the component gets the correct value for each record but when I run the code, it always gets the parameters of first record in list.
Am I missing something ?
I think the main issue came from same Id for all components and when you click on a link first element with ID (confirmDeleteModal) will be opened.
You can set an unique id for each components like this:
<div class="modal fade" :id="'confirmDeleteModal_'+id" tabindex="-1"
role="dialog" aria-labelledby="confirmDeleteModalLabel">
I think calling the confirm-delete-modal for each record is a wrong method. I moved the modal outside the loop and made some changes to the code to solve the problem :
Here is the code of confirmDelete.vue :
<template id="modal-template">
<transition name="confirm-delete-modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot name="body">
Are you sure about deleting the {{ this.$parent.item_name }} {{ item }} ?
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
<button class="modal-default-button" #click="deleteItem();">
Yes
</button>
<button class="modal-default-button" #click="$emit('close')">
No
</button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
data () {
return {
}
},
props: ['item'],
methods: {
deleteItem : function() {
var url = window.location.href;
var baseUrl = url.substring(0, url.indexOf('/', url.indexOf('://') + 3) + 1);
var adminPosition = url.indexOf('admin/') + 6;
var entity = url.substring(adminPosition, url.indexOf('/', adminPosition));
this.$http.delete(baseUrl + "admin/" + entity + "/" + this.$parent.item_id).then((response) => {
if (response.body.status_code == '200') {
$("tr[data-id=" + this.$parent.item_id + "]").remove();
this.$emit('close');
// Display success message
}
});
}
},
filters: {
capitalize: function (value) {
if (!value) {
return '';
}
value = value.toString();
return value.charAt(0).toUpperCase() + value.slice(1);
}
}
}
</script>
And here is the blade template :
#foreach ($categories as $category)
<tr data-id="{{ $category->id }}">
<td>{{ $category->id }}</td>
<td>{{ $category->name }}</td>
<td id="actions">
Show
Edit
Delete
</td>
</tr>
#endforeach
<confirm-delete-modal item="category"
v-if="showDeleteModal"
#close="closeDeleteModal">
<h3 slot="header">Delete Category</h3>
</confirm-delete-modal>
And finally here is the code of parent vue instance :
new Vue({
el: '#crud',
data: {
showDeleteModal: false,
item_id: '',
item_name: ''
},
methods: {
setDeleteModal: function(e) {
this.showDeleteModal = true;
params = e.target.id.split("_");
this.item_id = params[1];
this.item_name = params[0];
},
closeDeleteModal: function() {
this.showDeleteModal = false;
}
}
});
I hope this helps someone else.
I'll be glad to know the idea of experts in vuejs.
You need to use v-bind when passing variables as props, like following"
<confirm-delete-modal item="category" v-bind:id="{{ $category->id }}" v-bind:name="{{ $category->name }}"></confirm-delete-modal>
or in short you can replace v-bind with : as:
<confirm-delete-modal item="category" :id="{{ $category->id }}" :name="{{ $category->name }}"></confirm-delete-modal>

Resources