Download files in Razor Pages by AJAX method - ajax

I have a form with large no:of fields to input data.
The Page also has file upload option like below
Want to download the files without submitting this form and also without refreshing this page. what have done so far is
#if (Model.AttachForms != null)
{
<div class="form-row mt-1">
<div class="col-md-12">
<ul class="list-group">
#foreach (var item in Model.AttachForms)
{
<li class="list-group-item d-flex justify-content-between align-items-center pt-1 pb-1">
#Html.DisplayFor(modelItem => item.Name)
<button class="badge badge-primary badge-pill" value="#item.Name" id="FileDownloadBtn">Download</button>
</li>
}
</ul>
</div>
</div>
}
Javascript Code
$("#FileDownloadBtn").click(function () {
event.preventDefault();
var rootPath = '#Url.Content("~")';
$.ajax({
type: "post",
url: rootPath + "/RequestFormEdit?handler=FileDownload",
data: { filename: this.value },
success: function (data) {
}
})
})
cshtml.cs
public IActionResult OnPostFileDownload(string filename)
{
//string DownloadFileName = filename;
if (filename != null)
{
var Folder = RequestID.ToString();
string fileview = Path.Combine(_env.WebRootPath, "Documents", Folder, filename);
WebClient User = new WebClient();
Byte[] fileBuffer = System.IO.File.ReadAllBytes(fileview);
if (fileBuffer != null)
{
return File(fileBuffer, "application/octet-stream", filename);
}
}
return null;
}
My doubt is how can to pass this file content data as json string and download the file as same as the uploaded format.
Edited
Edited the filedownload button with formdata, but still its not working.
My doubt is i am passing file name in the download button like below
<ul class="list-group">
#foreach (var item in Model.AttachForms)
{
<li class="list-group-item d-flex justify-content-between align-items-center pt-1 pb-1">
#Html.DisplayFor(modelItem => item.Name)
<button class="badge badge-primary badge-pill" value="#item.Name" id="FileDownloadBtn">Download</button>
</li>
}
</ul>
Do i need to give get().files in jquery?
$("#FileDownloadBtn").click(function () {
event.preventDefault();
var formData = new FormData();
var rootPath = '#Url.Content("~")';
var files = $("#FileDownloadBtn").get(0).files;
formData.append('Files', files[0]);
$.ajax({
type: "post",
url: rootPath + "/RequestFormEdit?handler=FileDownload",
data: formData,
processData: false,
contentType: false,
success: function (data) {
}
})
})
This is my backend code to download
public IActionResult FileDownload(string filename)
{
//string DownloadFileName = filename;
if (filename != null)
{
var Folder = RequestFormMaster.RequestID.ToString();
var fileUploadPath = _fileuploadurl;
string fileview = Path.Combine(fileUploadPath, Folder, filename);
WebClient User = new WebClient();
Byte[] fileBuffer = System.IO.File.ReadAllBytes(fileview);
if (fileBuffer != null)
{
return File(fileBuffer, "application/octet-stream", filename);
}
}
return null;
}
FILE UPLOAD
<div class="col-sm-4 mb-2 pl-sm-2" >
<label class="pl-4 pt-2"><b>Upload Attachments</b></label>
<div class="form-row" style="border:3px dashed #D3D3D3;outline-offset:-10px;height:75px;border-radius:5px;">
<div class="col-md-12">
<label for="attachment" style="padding: 15px 145px;">
<a class="btn" style="background-color:#E9ECEF;" role="button" aria-disabled="false">Click here to upload files</a>
</label>
<input id="attachment" style="visibility: hidden; position: absolute; display: block;" type="file" asp-for="ReqSupportingFiles" multiple>
</div>
</div>
#if (Model.AttachForms != null)
{
<div class="form-row mt-1">
<div class="col-md-12">
<ul class="list-group">
#foreach (var item in Model.AttachForms)
{
<li class="list-group-item d-flex justify-content-between align-items-center pt-1 pb-1">
#Html.DisplayFor(modelItem => item.Name)
<button class="badge badge-primary badge-pill" value="#item.Name" id="FileDownloadBtn">Download</button>
</li>
}
</ul>
</div>
</div>
}
<div class="form-row mt-1">
<div class="col-md-12">
<p id="files-area">
<span id="filesList">
<span id="files-names"></span>
</span>
</p>
</div>
</div>
</div>

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"]);
}
}
}

Boostrap Modal, browse for photo and submit via ajax to controller with [FromForm] IFormFile file

I want to create a reusable upload feature for images and have created a partialView for this. On click, the partial is loaded via ajax call and the user can browse for an image, the chosen image is displayed and on submit the file should be passed to the controller but the url for submission is always a 404.
Load the Bootstrap Modal
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="ajax-modal" data-target="#add-contact" data-url="#Url.Action("ShowModalUploadForm", new { Id= Model.Id })">
Add contact
</button>
var placeholderElement = $('#modal-placeholder');
$(document).on('click', 'button[data-toggle="ajax-modal"]', function (event) {
var url = $(this).data('url');
$.get(url).done(function (data) {
placeholderElement.html(data);
placeholderElement.find('.modal').modal('show');
});
});
This works...The issue is when I submit, the URL that is fored appears to not match what the controller is expecting
PartialView (omitted unnecessary portions)
<form id="UploadPhoto" asp-action="UploadPhoto" enctype="multipart/form-data" method="post">
<input name="VolunteerId" id="VolunteerId" type="hidden" value="#Model" />
<div class="col-md-12">
<div class="form-group">
<label>Upload Image</label>
<div class="input-group">
<span class="input-group-btn">
<span class="btn btn-default btn-file">
Browse… <input type="file" id="imgInp">
</span>
</span>
<input type="text" class="form-control" readonly>
</div>
<img id='img-upload' name='img-upload' />
</div>
</div>
</form>
$(document).on('click', '#btnSubmitUpload', function (event) {
event.preventDefault();
var form = $(this).parents('.modal').find('form');
var dataToSend = new FormData(form.get(0));
$.ajax({
url: '#Url.Action("UploadPhoto", "Volunteer", new { Area = "Admin" })',
method: 'post',
data: dataToSend,
processData: false,
contentType: false
}).done(function (data) {
//Do stuff here
}
});
});
$(document).on('change', '.btn-file :file', function () {
var input = $(this),
label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
input.trigger('fileselect', [label]);
});
$(document).on('fileselect', '.btn-file :file', function (event, label) {
var input = $(this).parents('.input-group').find(':text'),
log = label;
if (input.length) {
input.val(log);
} else {
if (log) alert(log);
}
});
$(document).on('change', '#imgInp', function () {
readURL(this);
});
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#img-upload').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
VolunteerController
[HttpPost]
private async void UploadPhoto([FromForm] IFormFile file)
{
//await _storage.SaveBlobAsync("volunteers", file, BlobType.Image);
}
Open the F12 developer tools, where is your misalignment? Or we can also use the FormData object.
View:
#model ImageFileUpload.Models.Human
#{
ViewBag.Title = "SaveData";
}
<h2>SaveData</h2>
<div>
Create New
<br /><br />
<table class="table table-responsive">
<thead>
<tr style="background-color:#333;color:white;">
<th>Human Name</th>
<th>Human Image</th>
<th>Human Phone</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody id="SetHumanList">
<tr id="LoadingStatus"></tr>
</tbody>
</table>
</div>
#using (Html.BeginForm("SaveData", "Human", FormMethod.Post, new { id = "form", enctype = "multipart/form-data" }))
{
<div class="modal fade" id="MyModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
×
<h4 id="ModalTitle"></h4>
</div>
<div class="modal-body">
<fieldset id="SubmitForm">
#Html.HiddenFor(a => a.HumanId, new { #id = "HumId" })
<div class="form-group">
#Html.TextBoxFor(a => a.HumanName, new { #id = "HumName", #class = "form-control", #placeholder = "Name" })
</div>
<div class="form-group">
<input type="file" id="UploadFile" name="Upload" class="form-control w" />
</div>
<div class="form-group">
#Html.TextBoxFor(a => a.HumanPhone, new { #id = "HumPhone", #class = "form-control", #placeholder = "Phone" })
</div>
<div class="form-group">
<button id="SaveRecord" type="button" class="btn btn-warning">Create</button>
</div>
</fieldset>
</div>
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
<script src="~/Scripts/jquery.form.min.js"></script>
#Scripts.Render("~/bundles/jqueryval")
<script>
function AddNewHuman() {
$("#MyModal").modal("show")
}
$("#SaveRecord").click(function () {
var formData = new FormData();
formData.append("Upload", $('#UploadFile')[0].files[0]); //append the image file
var other_data = $('form').serializeArray();
$.each(other_data, function (key, input) { //append other input value
formData.append(input.name, input.value);
});
$.ajax({
type: "POST",
url: "/Human/SaveData",
data: formData,
contentType: false, // Not to set any content header
processData: false, // Not to process data
success: function (result) {
alert("Success");
window.location.href = "/Human/index";
//$("#MyModal").modal("hide"); //this line is unnecessary because the user has been redirect
}
})
});
</script>
}
Result

How to reload a page in laravel vue after save?

I'm trying to reload the page after save in laravel and vue.js, I do this in "fetchGoals". Here is what I've tried and it works the first time, it saves the goal and refreshes the page. When I try to add another goal then the save button no longer works and the page will not refresh. Same goes for the edit button, it will work the first time and then the second time it will not. Regardless if is save or edit, the same problem exists where I can only perform one function where the pages refreshes. Any ideas what I'm doing wrong?
<template>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">
<form #submit.prevent="addGoal" class="mb-3">
<div class="form-group">
<input type="text" class="form-control" placeholder="Goal" v-model="goal.title">
</div>
<div class="form-group">
<textarea class="form-control" placeholder="Description" v-model="goal.description">
</textarea>
</div>
<button type="submit" class="btn btn-primary btn-block">Add New Goal</button>
</form>
<button #click="clearForm()" class="btn btn-danger btn-block">Cancel</button>
<div class="panel-body">
<table class="table">
<thead>
<tr>
<th scope="col">id</th>
<th scope="col">Title</th>
<th scope="col">Description</th>
</tr>
</thead>
<tbody>
<tr v-for="goal in goals" v-bind:key="goal.id">
<td>{{goal.id}}</td>
<td>{{goal.title}}</td>
<td>{{goal.description}}</td>
<td>
<button #click="editGoal(goal)" class="btn btn-warning btn-xs">Edit</button>
</td>
<td>
<button #click="deleteGoal(goal.id)" class="btn btn-danger btn-xs">Delete
</button>
</td>
</tr>
</tbody>
</table>
<nav aria-label="Page navigation example">
<ul class="pagination">
<li v-bind:class="[{disabled: !pagination.prev_page_url}]" class="page-item">
<a class="page-link" href="#" #click="fetchGoals(pagination.prev_page_url)">Previous</a>
</li>
<li class="page-item disabled">
<a class="page-link text-dark" href="#">Page {{ pagination.current_page }} of {{
pagination.last_page }}</a>
</li>
<li v-bind:class="[{disabled: !pagination.next_page_url}]" class="page-item">
<a class="page-link" href="#"
#click="fetchGoals(pagination.next_page_url)">Next</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
goals: [],
goal: {
id: '',
title: '',
description: '',
user_id: 1,
},
goal_id: '',
pagination: {},
edit: false
};
},
created() {
this.fetchGoals();
},
methods: {
//gets the data and the pagination
fetchGoals(page_url) {
let vm = this;
page_url = page_url || '/api/goals';
fetch(page_url)
.then(res => res.json())
.then(res => {
this.goals = res.data;
//this comes from res and res is the data from the Jason
vm.makePagination(res.meta, res.links);
})
.catch(err => console.log(err));
},
addGoal() {
if (this.edit === false) {
// Add
fetch(`/api/goal`, {
method: 'post',
body: JSON.stringify(this.goal),
headers: {
'content-type': 'application/json',
}
})
.then(res => res.json())
.then(data => {
this.clearForm();
alert('Article Added');
this.fetchGoals();
})
.catch(err => console.log(err));
} else {
//Edit save
fetch(`/api/goal`, {
method: 'put',
body: JSON.stringify(this.goal),
headers: {
'content-type': 'application/json',
}
})
.then(res => res.json())
.then(data => {
this.clearForm();
alert('Article Added');
this.fetchGoals();
})
.catch(err => console.log(err));
}
},
editGoal(goal) {
this.edit = true;
this.goal.id = goal.id;
this.goal.goal_id = goal.id;
this.goal.title = goal.title;
this.goal.description = goal.description;
},
clearForm() {
this.edit = false;
this.goal.id = null;
this.goal.goal_id = null;
this.goal.title = '';
this.goal.description = '';
this.goal.user_id = null;
}
}
};
</script>
You can use traditional JavaScript to solve your problem
// Reload the current page
window.location.reload();
Use window.location.reload(true); to force reload (ignore the browser cache)

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"

AJAX code not working on iPad only

We've created an event check-in page where nonprofits can add volunteers at an event. The page is working great on all platforms besides iPad. (iPhone Safari is working.)
On iPad, clicking id=add-volunteer button has no effect. Desired behavior is that clicking the button adds the volunteer name to the list of registered volunteers and saves the user info on the backend. (Other backend tasks such as sending an invite email should occur on the backend as well.)
HTML
<form id="form-add" method="post">
<input type="hidden" name="csrfmiddlewaretoken">
<div class="row one-margin-bottom center">
<div id="new-volunteers" class="small-12 medium-8 small-centered columns">
<h6 class="left">Add volunteer</h6>
<div class="row">
<div class="input-right small-6 columns">
<input class="center" id="new-firstname" name="user_firstname" placeholder="First name" type="text" required="">
</div>
<div class="input-right small-6 columns">
<input class="center" id="new-lastname" name="user_lastname" placeholder="Last name" type="text" required="">
</div>
<div class="input-right small-12 medium-12 columns">
<input class="lead center" id="new-email" name="user_email" placeholder="Email address" type="email" required="">
</div>
</div>
<div class="no-margin-top qtr-margin-bottom checkbox center">
<input type="checkbox" name="invite-optin" id="invite-optin" class="custom-checkbox" checked="">
<label for="invite-optin">Invite volunteer to openCurrents</label>
</div>
<a id="add-volunteer" class="half-margin-bottom button round small secondary">
Add volunteer
</a>
</div>
</div>
</form>
<form id="form-checkin" method="post">
<input type="hidden" name="csrfmiddlewaretoken">
<div class="row">
<div class="small-12 medium-8 small-centered columns">
<h6 class="left half-margin-bottom">Registered volunteers</h6>
<div class="row">
<div class="left small-8 columns">
<p class="small-text half-margin-top half-margin-bottom"><strong>Name / Email</strong></p>
</div>
<div class="right small-4 columns">
<p class="small-text half-margin-top half-margin-bottom"><strong>Check in</strong></p>
</div>
</div>
</div>
</div>
<div class="row">
<div id="registered-volunteers" class="small-12 medium-8 small-centered columns">
</div>
</div>
</form>
<div class="row">
<a href="/org-admin/" class="button round small secondary">
Back to org home
</a>
</div>
JS
let onCheckClick = function(event) {
let name = event.target.name;
let elem = $(`#${name}`);
let userid = elem.val();
let isChecked = elem.prop("checked");
$.ajax({
url: "{% url 'openCurrents:event_checkin' event_id %}",
type: 'POST',
data : {
csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[1].value,
userid: userid,
checkin: isChecked
},
dataType : "json",
context: document.body
}).done(function( data ){
// console.log('checkin request:');
// console.log(data);
if (isChecked) {
let dt = new Date();
$(`#vol-status-${userid}`).text(`${dt.toLocaleTimeString()}`);
$(`#vol-status-${userid}`).show();
}
else {
$(`#vol-status-${userid}`).text(`${data.responseText} min.`);
}
}).fail(function (data) {
// console.log('checkin error:')
// console.log(data);
elem.prop('checked', false);
$('#live-dashboard-error').slideDown();
});;
};
$(document).ready(function(){
// bind all existing checkbox to checkin
$("input[name^='vol-checkin']").click(onCheckClick);
$("#add-volunteer").click(function(event){
if ($(this).attr('disabled') === 'disabled') {
$('#live-dashboard-checkin-disabled').slideDown();
return;
}
if ($('#new-firstname').val() == '' || $('#new-lastname').val() == '' || $('#new-email').val() == '') {
$('#vol-error').slideDown();
} else if ( !(/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test($('#new-email').val() )) ) {
$('#vol-error').slideUp();
$('#email-error').slideDown();
} else {
$('#vol-error').slideUp();
$('#email-error').slideUp();
let new_firstname = $('#new-firstname').val();
let new_lastname = $('#new-lastname').val();
let new_email = $('#new-email').val();
let invite_optin = $('#invite-optin').prop('checked');
let process_signup_url;
let form_data = {
csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].value,
user_firstname: new_firstname,
user_lastname: new_lastname,
user_email: new_email.toLowerCase()
};
if (invite_optin) {
process_signup_url = "{% url 'openCurrents:process_signup' endpoint=True verify_email=True %}"
form_data['org_admin_id'] = {{ user.id }};
}
else {
process_signup_url = "{% url 'openCurrents:process_signup' endpoint=True verify_email=False %}"
}
form_data['signup_status'] = 'vol'
$.ajax({
url: process_signup_url,
type: 'POST',
data: form_data,
dataType : "json",
}).done(function( data ) {
// console.log('signup response:')
// console.log(data);
let userid = data;
let form_data = {
csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].value,
userid: userid
}
$.ajax({
url: "{% url 'openCurrents:event_register_live' eventid=event.id %}",
type: 'POST',
data: form_data,
dataType : "json",
}).done(function( data ) {
//console.log('register_live response:')
//console.log(data);
// hide any error messages present
$('#vol-exist').slideUp();
$('#live-dashboard-error-register').slideUp();
$('#live-dashboard-error').slideUp();
$('#vol-error').slideUp();
$('#email-error').slideUp();
$('#live-dashboard-not-in-progress').slideUp();
if (data.event_status >= 0) {
$('#registered-volunteers').prepend(`
<div class="row"> \
<div class="left small-9 columns"> \
<p class="half-margin-top"> \
${new_firstname} \
${new_lastname} \
</p> \
</div> \
<div class="right small-3 columns"> \
<input {% if checkin_disabled %}disabled{% endif %} type="checkbox" id="vol-checkin-${userid}" name="vol-checkin-${userid}" value="${userid}" class="hidden checkin-checkbox"/> \
<label class="checkin-checkbox-icon" for="vol-checkin-${userid}"> \
<i class="fa fa-lg fa-check-circle"></i> \
</label> \
</div> \
</div> \
`)
// clear form inputs
$('#new-firstname').val('');
$('#new-lastname').val('');
$('#new-email').val('');
$('#invite-optin').attr("checked", true);
// bind new checkbox to checkin
$(`input[name='vol-checkin-${userid}']`).click(onCheckClick);
if (data.event_status == 1) {
$(`input[name='vol-checkin-${userid}']`).trigger('click')
} else {
$('#live-dashboard-not-in-progress').slideDown();
}
}
else {
$('#new-firstname').val('');
$('#new-lastname').val('');
$('#new-email').val('');
$('#invite-optin').attr("checked", true);
$('#vol-exist').slideDown();
}
}).fail( function (data) {
// console.log('register_live error:')
// console.log(data);
$('#live-dashboard-error').slideDown();
});
}).fail(function (data) {
// console.log('signup error:')
// console.log(data);
$('#live-dashboard-error').slideDown();
});
}
});

Resources