I want to delete this product instantly when I click the delete button, so far when I click the delete button it hides the icon and the product is still showing until I refresh the page then the product is gone, how can I fix this?
Script
function deleteFromFavourites(productid, userid) {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
method: 'post',
url: `product/${productid}/unlike`,
data: {
'user_id': userid,
'product_id': productid,
},
success: function () {
console.log($('#deletefavourite' + productid));
// show delete button
$('#deletefavourite' + productid).hide();
},
});
}
Blade file
#foreach (Auth::user()->likedProducts as $product)
<h4>USD {{$product->price }}</h4>
<h1>USD {{$product->name }}</h1>
<a style="display: {{$product->isLiked ? "" : "none"}}" id="deletefavourite{{$product->id}}" onClick="deleteFromFavourites({{$product->id}}, {{ Auth::user() ? Auth::user()->id : 0 }})">Delete</a>
#endforeach
You must change to parent div of the product you want to hide instead of hiding the 'a' tag.
function deleteFromFavourites(this, productid, userid) {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
method: 'post',
url: `product/${productid}/unlike`,
data: {
'user_id': userid,
'product_id': productid,
},
success: function () {
// remove parent division on success
this.parent().remove();
},
});
}
in your blade wrap the product into div.
#foreach (Auth::user()->likedProducts as $product)
<div id="parentDiv">
<h4>USD {{$product->price }}</h4>
<h1>USD {{$product->name }}</h1>
<a style="display: {{$product->isLiked ? "" : "none"}}" id="deletefavourite" data-user_id="{{ Auth::user() ? Auth::user()->id : 0 }}" data-product_id="{{$product->id}}">Delete</a>
</div>
#endforeach
Another workaround is to remove the onclick and add onclick function to your js.
$('#deletefovourite').click(function(){
deleteFromFavourites($(this), $(this).data('product_id'),$(this).data('user_id'));
})
Related
Here is a div that I append in AJAX with a script (at the bottom of the TWIG file) :
<div>
{% for vote in proposal.votes %}
{% if app.user == vote.user %}
<a href="{{ path('vote_delete',{'proposal' : proposal.id, 'vote' : vote.id}) }}"
class="btn btn-light ml-1 btn-sm">
</a>
{% endif %}
{% endfor %}
</div>
If I then click on the freshly appended button, it returns an error because the ID "vote.id" is still 0 until I reload the page and the ID gets found...
Is there a way to trigger the for loop without reloading the page to get the ID directly after its creation? Is it linked with "async" or any "ready" function?
EDIT :
The script that appends the div #deleteVote when I vote :
$(document).on('click', '.votedFullAgreement', function (event){
event.preventDefault();
$.ajax({
url: '{{ path('vote_add', {'slug' : slug, 'proposal' : proposal.id, 'userVote' : 'votedFullAgreement', 'user' : app.user.id }) }}',
type: 'POST',
dataType: 'html',
success: function (){
if( $('#deleteVote').length === 0 ) {
//The whole HTML of the div
},
error: function (resultat, statut, erreur) {
console.error(erreur);
}
});
});
The #deleteVote that gets appended, with the url of the "deleteVote" function (which needs to know the ID of the vote to delete) :
$(document).on('click', '.deleteVote', function (event){
event.preventDefault();
$.ajax({
url: '{{ path('vote_delete', {'slug' : slug, 'proposal' : proposal.id, 'vote' : vote.id }) }}',
type: 'POST',
dataType: 'html',
success: function (){
$('#deleteVote').slideUp();
},
});
});
As I've mentioned in the comments, you can't pass a javascript directly to twig, as twig is rendered serverside. One way to solve this is to calculate all the path beforehand:
{% for vote in proposal.votes %}
...
<button type="button" class="votedFullAgreement" data-path="{{ path('vote_add', {'slug' : slug, 'proposal' : proposal.id, 'userVote' : 'votedFullAgreement', 'user' : app.user.id }) }}">Add vote</button>
...
{% endfor %}
Now you can access the path directly in javascript
$(document).on('click', '.votedFullAgreement', function (event){
event.preventDefault();
$.ajax({
url: $(this).data('path'),
type: 'POST',
dataType: 'html',
success: function (){
if( $('#deleteVote').length === 0 ) {
//The whole HTML of the div
},
error: function (resultat, statut, erreur) {
console.error(erreur);
}
});
});
You could also make an extra request to a controller to generate the path, but this would mean you would need to pass all the variables, e.g. slug, app.user.id, ...
More information on how to generate a path inside a controller can be found here
i try to create a shop cart using ajax (add working 100% )
but when i try to remove item(s) i found button not clickable
this is the code of delete :
$(document).on('click', '.delete', function() {
var product_id = $(this).attr("id");
var action = "remove";
console.log('something'); // show nothing
$.ajax({
url: "action.php",
method: "POST",
dataType: "json",
data: {
product_id: product_id,
action: action
},
success: function(data) {
$('#order_table').html(data.order_table);
$('#order_footer').html(data.order_footer);
$('.badge').text(data.cart_item);
}
});
})
Button code :
<button class="text-danger delete" id="<?php echo $values["product_id"]; ?>" >
<i data-feather="x"></i>
</button>
I just implemented SortableJS in my Laravel project and want to rearrange the order of some elements. I have a list of "Blocks" which all have a database field of "Order" which is an integer. I show these blocks in descending order based on the value of the "Order" field.
Now I want to update these values with SortableJS using Ajax. How can I accomplish this?
Currently, I have a simple list
<div class="block-order-list">
#foreach($blocks as $block)
<div class="list-group-item"><i class="far fa-arrows handle mr-3"></i> {{$block->name}}</div>
#endforeach
</div>
And call an Ajax request like so:
$('.block-order-list').sortable({
animation: 150,
handle: '.handle',
store: {
set: function (sortable) {
let order = sortable.toArray();
console.log(order);
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url: '{{ route('change_order', ['url', $page->url]) }}',
type: 'POST',
data: order,
success: function(data){
console.log(data)
}
})
}
}
});
To my PageController which contains
public function changeOrder($data)
{
return $data;
}
The request now only returns a string that says url which I find odd. In the url of the ajax request, I give a parameter called URL which I need to find the blocks attached to this specific page. My blocks database table looks like this
How can I accomplish this?
I guess you must use ID in your HTML list :
<div class="block-order-list">
#foreach($blocks as $block)
<div class="list-group-item" data-id="{{ $block->id }}>
<i class="far fa-arrows handle mr-3"></i> {{ $block->name }}
</div>
#endforeach
</div>
Then in your JS, build an array with ID => order :
let order = {};
$('.list-group-item').each(function() {
order[$(this).data('id')] = $(this).index();
});
Then in your ajax call :
$.ajax({
url: '{{ route('change_order', ['url', $page->url]) }}',
type: 'POST',
data: {order: order},
success: function(data){
console.log(data)
}
})
And in your controller :
public function changeOrder(Request $request)
{
foreach($request->get('order') as $id => $order) {
Block::find($id)->update(['order' => $order]);
}
}
I'm creating this functionality where user can like a product and unlike it with javascript, if user likes the product it should add to the database and also if he unlike the product it should be deleted in database. Everything works fine in normal way but if I use javascript, the like button isn't working and either not adding anything in database same thing applies for unlike button. How can I make this work (like and unlike this should work in database too not changing the icons of like and unlike)?
Javascript
// Like product
function addToFavourites(productid, userid) {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
method: 'post',
url: `/product/like/${productid}`,
data: {
'user_id': userid,
'product_id': productid,
},
success: function () {
// hide add button
$('#addfavourites' + productid).hide();
// show delete button
$('#deletefavourite' + productid).show();
},
error: function (XMLHttpRequest) {
// handle error
}
});
// Unlike product
function deleteFromFavourites(productid, userid) {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
method: 'post',
url: `product/${productid}/unlike`,
data: {
'user_id': userid,
'product_id': productid,
},
success: function () {
// hide add button
$('#addfavourites' + productid).hide();
// show delete button
$('#deletefavourite' + productid).show();
},
error: function (XMLHttpRequest) {
// handle error
}
});
Route
Route::post('product/like/{id}', ['as' => 'product.like', 'uses' => 'LikeController#likeProduct']);
Route::post('product/{product}/unlike', 'LikeController#destroy')->name('product.unlike');
Blade File
#if($product->isLiked)
<div id="deletefavourite{{$product->id}}"onClick="deleteFromFavourites({{$product->id}}, {{ Auth::user()->id }})"> unlike </div>
#else
<div id="addfavourites{{$product->id}}" onClick="addToFavourites({{$product->id}}, {{ Auth::user()->id }})" > like </div>
#endif
How I add to favorite
public function likeProduct($id)
{
if(Auth::check()){
$this->handleLike(Product::class, $id);
return redirect()->back();
}
else{
return redirect()->route('login')
}
}
public function handleLike($type, $id)
{
$existing_like = Like::withTrashed()->whereLikeableType($type)->whereLikeableId($id)->whereUserId(Auth::id())->first();
if (is_null($existing_like)) {
Like::create([
'user_id' => Auth::id(),
'likeable_id' => $id,
'product_id' => $id,
'likeable_type' => $type,
]);
} else {
if (is_null($existing_like->deleted_at)) {
$existing_like->delete();
} else {
$existing_like->restore();
}
}
}
I think you have not completed curly braces of function check my code
function addToFavourites(productid, userid) {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
method: 'post',
url: `/product/like/${productid}`,
data: {
'user_id': userid,
'product_id': productid,
},
success: function () {
// hide add button
console.log($('#addfavourites' + productid));
$('#addfavourites' + productid).hide();
// show delete button
$('#deletefavourite' + productid).show();
},
error: function (XMLHttpRequest) {
// handle error
}
});
}
// Unlike product
function deleteFromFavourites(productid, userid) {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
method: 'post',
url: `product/${productid}/unlike`,
data: {
'user_id': userid,
'product_id': productid,
},
success: function () {
// hide add button
console.log($('#addfavourites' + productid));
$('#addfavourites' + productid).hide();
// show delete button
$('#deletefavourite' + productid).show();
},
error: function (XMLHttpRequest) {
// handle error
}
});
}
first you must check in network for see request and response from inspect element
this thing will make you can follow problem . you may have a problem with route so please
check the network during post request.
First of all I suggest change routes. I mean, use same pattern for both actions: like and unlike
Route::post('product/like/{id}', ['as' => 'product.like', 'uses' => 'LikeController#likeProduct']);
Route::post('product/unlike/{id}', 'LikeController#destroy')->name('product.unlike');
Then inspect what you see on server, log incoming data. It should help to understand, why you algorithm didn't work.
Second, you have to render both div's in your blade template
<div class="CLASS_SHOW_ITEM" id="deletefavourite{{$product- >id}}"onClick="deleteFromFavourites({{$product->id}}, {{ Auth::user()->id }})"> unlike </div>
<div class="CLASS_HIDE_ITEM" id="addfavourites{{$product->id}}" onClick="addToFavourites({{$product->id}}, {{ Auth::user()->id }})" > like </div>
You have to choose class by value of attribute $product->isLiked
I wonder why its not working, here is the code
View
<input type="button" value="Delete" onclick="deletefunction(#item.PhotoId)"/>
Controller
[HttpPost]
public ActionResult Delete(int photoid)
{
var imgDelete = db.Photos.Where(x => x.PhotoId == photoid).FirstOrDefault();
if (imgDelete == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
db.Photos.Remove(imgDelete);
db.SaveChanges();
System.IO.File.Delete(AppDomain.CurrentDomain.BaseDirectory + imgDelete.ImagePath);
System.IO.File.Delete(AppDomain.CurrentDomain.BaseDirectory + imgDelete.ThumbPath);
return null;
}
JQUERY/AJAX
<script type="text/javascript">
$(document).ready(function () {
function deletefunction(photoid) {
$.ajax({
url: '#Url.Action("Delete")',
type: 'POST',
data: { photoid: photoid },
success: function (result) {
alert: ("Success")
},
error: {
alert: ("Error")
}
});
};
});
</script>
im new to jquery and ajax, im trying to delete the photo without refreshing the page, am i in the correct path?
I would suggest to attach click event to your button instead of writing javascript in markup. Consider the below markup:
<input type="button" class="delete" value="Delete" data-picid="#item.photoId"/>
Now attach a click event to .delete as below:
$('.delete').on('click',function(){
var photoId=$(this).attr('data-picid');//gets your photoid
$.ajax({
url: '#Url.Action("Delete")',
type: 'POST',
data: JSON.stringify({ photoid: photoId }),
contentType: "application/json; charset=utf-8",
dataType: "json", //return type you are expecting from server
success: function (result) {
//access message from server as result.message and display proper message to user
alert: ("Success")
},
error: {
alert: ("Error")
}
});
});
Your Controller then:
[HttpPost]
public ActionResult Delete(int photoid)
{
var imgDelete = db.Photos.Where(x => x.PhotoId == photoid).FirstOrDefault();
if (imgDelete == null)
{
return Json(new{ message=false},JsonRequestBehavior.AllowGet);//return false in message variable
}
db.Photos.Remove(imgDelete);
db.SaveChanges();
System.IO.File.Delete(AppDomain.CurrentDomain.BaseDirectory + imgDelete.ImagePath);
System.IO.File.Delete(AppDomain.CurrentDomain.BaseDirectory + imgDelete.ThumbPath);
return Json(new{ message=false},JsonRequestBehavior.AllowGet); //return true if everything is fine
}
Once photo is deleted based on the success or failure your can do it as below in success of ajax, but before that store a reference to yourbutton` as below:
$('.delete').on('click',function(){
var photoId=$(this).attr('data-picid');//gets your photoid
var $this=$(this);
$.ajax({
url: '#Url.Action("Delete")',
type: 'POST',
data: JSON.stringify({ photoid: photoId }),
contentType: "application/json; charset=utf-8",
dataType: "json", //return type you are expecting from server
success: function (result) {
if(result.message)
{
$this.closest('yourrootparentselector').remove();
//here yourrootparentselector will be the element which holds all
//your photo and delete button too
}
},
error: {
alert: ("Error")
}
});
});
UPDATE
Based on your given mark up you I suggest to add one more root parent for your each image and delete button as below:
<div style="margin-top: 17px;">
<div id="links">
#foreach (var item in Model.Content)
{
<div class="rootparent"> <!--rootparent here, you can give any classname-->
<a href="#item.ImagePath" title="#item.Description" data-gallery>
<img src="#item.ThumbPath" alt="#item.Description" class="img-rounded" style="margin-bottom:7px;" />
</a>
<input type="button" class="delete" value="Delete" data-picid="#item.PhotoId" />
</div>
}
</div>
</div>
Now you can write this in success
$this.closest('.rootparent').remove()
Try this.
<script type="text/javascript">
$(document).ready(function () {
});
function deletefunction(photoid) {
$.ajax({
url: '#Url.Action("Delete")',
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: "json",
data: { photoid: photoid },
success: function (result) {
alert: ("Success")
},
error: {
alert: ("Error")
}
});
}
</script>