Laravel 8 - ajax removing first row - html

I'm beginner in Ajax and I'm using Laravel 8. I want to remove row that from database but when I try this code it's removing first row but it needs to remove the returned id row. How can I remove the row?
My blade is:
<div class="anime__review__item" id="testp" >
<div class="anime__review__item__pic">
<img src="<?=url('/')?>/images/avatars/{{$comment->user->photo}}" alt="">
</div>
<div class="anime__review__item__text" >
<h6><a href="{{route('getProfile', ['username'=> $comment->user->username])}}" >{{$comment->user->name }}</a></a><span >{{$comment->created_at->diffForHumans()}}</span></h6>
<p> {{$comment->comment }}</p>
<p class="card-text"><span class="icon_trash" type="button" data-id="{{ $comment->id }}" data-target="#default{{ $comment->id }}"></span></p>
</div>
</div>
My ajax is:
$(".icon_trash").click(function(event){
event.preventDefault();
var id = $(this).data("id");
Swal.fire({
title: 'Are you sure?',
text: "You won't be able to revert this!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
}).then((result) => {
if (result.isConfirmed) {
$.ajax({
url: "{{ route('deleteComments',['id' => $comment->id]) }}",
type: 'POST',
data: {
_token: "{{ csrf_token() }}",
id: id
},
success: function (){
$("#testp").remove();
},
error: function(){
alert('errorr');
},
})
}
})
});
My controller is:
public function deleteComments($id){
$deletedata= Comment::findOrFail($id);
$deletedata->delete();
if($deletedata){
return response()->json(['status'=>'testss']);
}else{
return back();
}
}

Since all divs have same ID, you have this issue. To solve, have unique IDs and unique removals as below:
Have dynamic value for div ID as:
<div class="anime__review__item" id="testp_{{ $comment->id }}">
Remove the respective ID accordingly in your ajax code as:
$("#testp_{{ $comment->id }}").remove();
This way, you correctly remove the parent div of the respective deleted comment.

Related

Fetch data from database in Laravel 9 using Vue js 3

I wanted to read the data from the database and display it in the app.
I'm calling it like this :
<h2 class="lowongan1" v-for="value in list_lowongan"> {{ value.title }}</h2>
<p class="descJob1" v-for="value in list_lowongan">{{ value.body }}</p>
The script
export default {
data() {
return {
'form': {
title: '',
body: '',
},
list_lowongan: []
};
},
mounted() {
console.log('on mounted');
axios.get('post/list').then((response) => {
console.log(response.data)
this.list_lowongan = response.data
}).catch((error) => {
console.log(error)
});
},
The problem is, when I call it like that, It displays all the title in the database and the body in the database tables.
How can I make it so that it only display 1 title for each h2 class ?
Use a wrapping div to hold your content and then loop over the div like so:
<div v-for="value in list_lowongan">
<h2 class="lowongan1"> {{ value.title }}</h2>
<p class="descJob1">{{ value.body }}</p>
</div>
You have two for-loops independent of each other so they'll stack by themselves
You just need one for-loop to display a list of where each title and body are together
You can form it this way:
<div v-for="value in list_lowongan">
<h2>{{ value.title }}</h2>
<p>{{ value.body }}</p>
</div>
As per your requirement, No need to use multiple v-for loops for same data iteration. Instead you can achieve that by applying v-for in a wrapper element and then prints the object values inside that wrapper element.
Live Demo :
new Vue({
el: '#app',
data: {
list_lowongan: []
},
mounted() {
this.list_lowongan = [{
title: 'Title 1',
body: 'Body 1'
}, {
title: 'Title 2',
body: 'Body 2'
}, {
title: 'Title 3',
body: 'Body 3'
}]
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(value, index) in list_lowongan" :key="index">
<h2>{{ value.title }}</h2>
<p>{{ value.body }}</p>
</div>
</div>

Laravel pass id to my sql on button click from view

I am trying to activate or deactivate the products for a form using $product->status
The active button shows if $product->status is 0 and
The deactive button shows if $product->status is 1
I want to toggle the value of $product->status in the mysql database every time I click on the button
<form action="{{route('invetory.create')}}" method="POST">
#csrf
<table class="table table-bordered" id="dynamicTable">
<tr>
<th>item</th>
<th>tax</th>
<th>Action</th>
</tr>
#forelse($products as $product)
<input type="text" name="item" value="{{$product->id}}
class="form-control" hidden />
<td>
<input type="text" name="item" value="{{$product->item}}
class="form-control" />
</td>
<td>
<input type="text" name="tax" value="{{$product->tax}}
class="form-control" />
</td>
#if($product->status =='0')
<td>
<button type="button" data-id="{{ $product->id }}" class="btn btn-success remove-tr active_btn">active</button>
</td>
#else
<td>
<button type="button" data-id="{{ $product->id }}" class="btn btn-danger remove-tr deactive_btn">Deactive</button>
</td>
#endif
</table>
</form>
here i have given the route i have used
web.php
Route::post('/update', 'App\Http\Controllers\InventoryController#update')>name('invetory.update');
here i have added the controler i have used
InventoryController.php
public function update(Request $REQUEST){
dd($REQUEST->all());
Inventory::update( $REQUEST->invetory as $key => $value);
return redirect()->action([InventoryController::class, 'index']);
}
i am geting 500 error when i click button
You can achieve this using POST request which will refresh the page each time you toggle a product or you can use AJAX to do the change asynchronously. Using Javascript and AJAX would be the preferred way so you don't lose selected filters, pagination etc.
You don't need external packages to implement that, you can use JavaScript's fetch method. Also, instead of having 2 separate functions and routes, I would suggest having one route that would toggle the product's status, i.e. if it is active, make it inactive and vice versa. That method by definition should be a POST request, by I prefer doing GET requests for this in order to avoid CSRF protection and use middleware to protect the request.
Here is the complete code.
Register a web route that toggles the state inside web.php
Route::get('projects/toggle', [ProjectController::class, 'toggle'])->name('projects.toggle');
Implement the toggle method in ProjectController.php
public function toggle(Request $request) {
$project = Project::find($request->project_id);
$project->status = !$project->status;
$project->save();
return response()->json(['status' => (int) $project->status]);
}
Notice that I am returning a json response which includes the new project status. We will use this in the JavaScript code to dinamically update the column where the status is shown.
Finally, in the blade file, when iterating through the projects, the button click calls a function that will do the AJAX request. Notice that I am also adding an id attribute to the columns that contains the status so I can access it dinamically in order to update it.
#foreach($projects as $project)
<tr>
<td>{{$project->title}}</td>
<td id="project-status-{{$project->id}}">{{$project->status}}</td>
<td><button onClick="toggleStatus('{{$project->id}}')">Toggle</button></td>
</tr>
#endforeach
In this same file, we add the following JavaScript code. It accepts project_id as parameter which is passed from the button click, makes the ajax request to backend which updates the status and then updates the appropriate DOM element to show the new status.
function toggleStatus(project_id) {
fetch("{{ route('projects.toggle') }}?project_id=" + project_id)
.then(response => response.json())
.then(response => {
document.querySelector("#project-status-" + project_id).innerHTML = response.status;
})
}
As I mentioned, you can use multiple options in the JavaScript part. Instead of calling a function you can register an event listener to each button, but this approach with function call is a bit quicker. Also, I am passing the project_id as GET parameter, you can define the route to contain it as route parameter, but then you'll need to do some string replacements in order to do in dinamically in JavaScript. All in all, the proposed is a good solution that will serve your purpose.
p.s. For stuff like this, LiveWire is a perfect fit.
Using dd (e.g. in your controller) will throw a 500 error. It literally stands for "dump and die".
check you routes in form use{{route('invetory.create')}}
and in routes you given inventory.update
public function Stauts(Request $request)
{
$product= Product::findOrFail($request->id);
$product->active == 1 ? $product->active = 0 : $product->active = 1 ;
$product->update();
return response()->json(['status' => true,'msg' => 'Staut updated']);
}
in blade use ajax
<script>
$(document).on('click', '.status-product', function (e) {
e.preventDefault();
var product_id = $(this).data('id');
var url ="{{ route('product.status') }}";
$.ajax({
type: "post",
url: url,
data: {
'_token': "{{csrf_token()}}",
'id': product_id
},
success: function (data) {
if (data.status == true) {
$('#deactive_ajax').show();}
}
})
})
</script>
Route::post('product/stauts/', [productController::class,'Stauts'])->name('product.Stauts');
First of all
Using a form with tables is not ideal and some browsers already made changes to prevent that.
Secondly
The best way is as DCodeMania said, the ajax request is the best way to solve this, I'll just modify his answer a bit and use Patch instead of PUT, so it'll look like this:
$(document).on('click', '.active_btn', function(e) {
e.preventDefault();
let id = $(this).data('id');
$.ajax({
url: '{{ route("products.update") }}',
method: 'PATCH',
data: {
id: id,
_token: '{{ csrf_token() }}'
},
success: function(response) {
console.log(response);
}
});
});
and you'll only be needing one button so no need to make the check for $product->status he added, just a single button for the toggle will make your code cleaner.
As for using PATCH instead of PUT, because you're only updating one single column and not the whole thing getting updated, and no need for the status parameter, you'll just reverse what's inside the database
$product = Product::find($request->id);
Product::where('id', $product->id)->update([
'status' => $product->status ? 0 : 1,
]);
You'll also need one button with different text based on status
like this
<td>
<button type="button" data-id="{{ $product->id }}" class="btn btn-success remove-tr active_btn">{{ $product->status == 1 ? 'deactivate' : 'activate' }}</button>
</td>
I did it this way and it works for me
First in view does this
<td>
#if ($producto->estado == '1')
<a href="{{ url('/status-update-producto', $producto->id) }}"
class="btn btn-success" id="btn_estado">Activo</a>
#else
<a href="{{ url('/status-update-producto', $producto->id) }}"
class="btn btn-danger" id='btn_estado'>Inactivo</a>
#endif
</td>
Controller
function updateStatusProducto($id)
{
//get producto status with the help of producto ID
$producto = DB::table('productos')
->select('estado')
->where('id', '=', $id,)
->first();
//Check producto status
if ($producto->estado == '1') {
$estado = '0';
} else {
$estado = '1';
}
//update producto status
$values = array('estado' => $estado);
DB::table('productos')->where('id', $id)->update($values);
return redirect()->route('productos.index');
}
Route
Route::get('/status-update-producto/{id}', [ProductoController::class, 'updateStatusProducto']);
You could add some data attributes to your buttons, and use them in js to send an ajax request
#if ($product->status =='0')
<td>
<button type="button" class="btn btn-success toggle-tr" data-product="{{ $product->id }}" data-status="{{ $product->status }}">active</button>
</td>
#else
<td>
<button type="button" class="btn btn-danger toggle-tr" data-product="{{ $product->id }}" data-status="{{ $product->status }}">Deactive</button>
</td>
#endif
document.querySelectorAll('.toggle-tr').forEach(el => el.addEventListener('click', e => {
const product = e.target.dataset.product;
const status = e.target.dataset.status == 0 ? 1 : 0;
// send ajax or fetch request passing in product_id. If we're going with a RESTful approach,
axiox.patch(`/products/${product}`, { status })
.then(res => { ... })
.catch(err => { ...});
}));
You can use jQuery ajax here:
Pass product id in data-id attribute
#if($product->status =='0')
<td>
<button type="button" data-id="{{ $product->id }}" class="btn btn-success remove-tr active_btn">active</button>
</td>
#else
<td>
<button type="button" data-id="{{ $product->id }}" class="btn btn-danger remove-tr deactive_btn">Deactive</button>
</td>
#endif
then use ajax:
$(document).on('click', '.active_btn', function(e) {
e.preventDefault();
let id = $(this).data('id');
$.ajax({
url: '{{ route("products.update") }}',
method: 'PUT',
data: {
id: id,
status: 1,
_token: '{{ csrf_token() }}'
},
success: function(response) {
console.log(response);
}
});
});
$(document).on('click', '.deactive_btn', function(e) {
e.preventDefault();
let id = $(this).data('id');
$.ajax({
url: '{{ route("products.update") }}',
method: 'PUT',
data: {
id: id,
status: 0,
_token: '{{ csrf_token() }}'
},
success: function(response) {
console.log(response);
}
});
});
Now you can handle the request in the controller.

Why ajax returns the latest variable of a loop in html template?

I have a html file as bellow:
<div id="preview_updated_notifications">
{% for lst in unread_list %}
<div >
<span data-notification-item="{{ lst.id }}" id="_mark_as_read_id"> ●</span>
</div>
{% endfor %}
</div>
and in js file:
$(document).on('click', "#_mark_as_read_id", function() {
var object_id = $('#_mark_as_read_id').data('notification-item');
console.log('--------------object_id:------------')
console.log(object_id)
console.log('--------------------------')
$.ajax({
type: "GET",
url: "{% url '_mark_as_read' object_id %}",
dataType: 'json',
data: {
'object_id': object_id,
},
dataType: 'json',
success: function (data) {
$('#preview_updated_notifications').html('**TEST**');
}
});
event.preventDefault();
});
But the problem is that this always prints the latest value of loop, while I expect after clicking on each item ● retrieve the relative id!
Ignoring the issue of the non-unique IDs you can delegate like this instead
$("#preview_updated_notifications").on("click","[data-notification-item]",function() {
const id = $(this).data("notification-item");
....
})
in
{% for lst in unread_list %}
<div >
<span data-notification-item="{{ lst.id }}" id="_mark_as_read_id"> ●</span>
</div>
{% endfor %}
many spans are rendered, and each of them has the same id. id should be unique in HTML, that is why only one span response to you.
{% url '_mark_as_read' object_id %} is a Django template tag, meaning that it gets rendered when the page first loads, so the value of object_id will always be the one initially passed as context, from the view.
You could use another HTML attribute, to store the update URL for each span, which would allow you to use the Django {% url ... %} tag.
Furthermore, as you have id="_mark_as_read_id" inside a for loop, every <span> element will have the same ID. IDs should be unique. You should use a class instead, and update the selector in the click function accordingly.
HTML:
<span data-notification-item="{{ lst.id }}" class="mark-as-read" data-update-link="{% url '_mark_as_read' lst.id %}"> ●</span>
jQuery:
$(document).on('click', ".mark-as-read", function() {
Then in your jQuery you could access it like this:
var update_url = $(this).data('update-link');
You are using django for loop for html only, the javascript code also needs to be in your for loop like this:
<div id="preview_updated_notifications">
{% for 1st in unread_list %}
<div >
<span data-notification-item="{{ lst.id }}" id="_mark_as_read_id{{ lst.id }}"> ●</span>
</div>
<script>
$(document).on('click', "#_mark_as_read_id{{ lst.id }}", function() {
var object_id = $('#_mark_as_read_id{{ lst.id }}').data('notification-item');
console.log('--------------object_id:------------')
console.log(object_id)
console.log('--------------------------')
$.ajax({
type: "GET",
url: "{% url '_mark_as_read' object_id %}",
dataType: 'json',
data: {
'object_id': object_id,
},
dataType: 'json',
success: function (data) {
$('#preview_updated_notifications').html('**TEST**');
}
});
event.preventDefault();
});
</script>
{% endfor %}
</div>
For every span html id, added {{ lst.id }}. So the id's will be like (_mark_as_read_id1, _mark_as_read_id2, _mark_as_read_id3, ....).
Now, it will get after clicking on each item ● retrieve the relative id!

Use modal on a v-for element?

I am getting a GET request from my api to disply all users , and i want to modify maybe the name of the email of each users with a modal. The problem is , imagine i have 3 users displayed , 3 modals will be displayed even if i press on only one modal button.
How can i do to fix it ?
there is my code :
<template>
<div class="container">
<div>
<h1>
<b> Users </b>
<input
type="text"
v-model="search"
class="search"
placeholder="Search User"
/>
</h1>
</div>
<div class="overlay-container">
<form>
<div class="form-group">
<div
v-for="user in filterUser"
v-bind:key="user"
class="form-control"
>
<p>
<b>{{ user.fname }} </b> {{ user.lname }}
</p>
<b-button v-b-modal.modal-1>Modifiy</b-button>
<b-modal id="modal-1" title="User Modification">
<p class="my-4">Please edit informations</p>
</b-modal>
</div>
</div>
</form>
</div>
</div>
</template>
<script>
import axios from "axios";
import VueAxios from "vue-axios";
export default {
name: "users",
data() {
return {
search: "",
users: [],
};
},
computed: {
filterUser() {
return this.users.filter((user) => {
return user.fname.match(this.search);
});
},
},
created() {
axios
.get(`http://localhost:4000/api/users`)
.then((Response) => (this.users = Response.data.data));
},
};
</script>
I want to each users open his own modal, not all modals when i press only one modal button.
I hope its clear !
First, pull out the modal inside of v-for, then create a method to get your user index, and add it to the Modify button. this is how you can get the data a user without sending another HTTP Request. and then you can show this.user data in your modal as you want.
<div
v-for="(user, index) in filterUser"
v-bind:key="user"
class="form-control"
>
<p>
<b>{{ user.fname }} </b> {{ user.lname }}
</p>
<b-button
v-b-modal.modal-1
#click="getUserInfo(index)"
>
Modifiy
</b-button>
</div>
data() {
return {
search: "",
users: [],
user: {}
};
},
methods: {
getUserInfo(index) {
this.user = this.users[index]
}
}

Trying to inject one html page into another after an AJAX call but returning blank

I'm trying to inject an html template with a django function on it, into another html template. The function rests on an AJAX call for its variables.
My AJAX call seems to be firing correctly (after checking in the Chrome dev tools) but the result is not showing on the html page as it should be.
Here is the AJAX call
//dashboard
$(document).ready(function(){
console.log('Document Ready')
$.ajax({
type: "GET",
url : '/electra/playlist',
dataType: "json",
data: {
'venue': 'venue',
'list': 'list',
},
success: function(data){
$("#playlist").html(data);
console.log(data)
},
failure: function(errMsg) {
alert(errMsg);
}
});
});
Here is the html file where the Django function occurs playlist.html
<!--what is the purpose of this fragmented code?-->
<div class="user_playlists">
<ul>
{% for item in playlist %}
<li>
<div>
<h6 class="playlist-name">{{ item.list }}</h6>
<h6 class="venue-name">{{ item.venue }}</h6>
</div>
</li>
{% endfor %}
</ul>
</div>
And here is the portion of the dashboard.html template where the playlist.html function should be injected:
<body>
{% block content %}
<div class="container-fluid" style="padding:15px">
<!--location -->
<div class="row">
<div class="col-sm-3">
<h3 class="list-heading"> Your Playlists </h3>
<div id="playlist">
</div>
</div>
</div>
</div>
{% endblock %}
Please note I have tried with {% include "playlist.html" %} and would like to avoid this if I can, I have another two html templates working in a similar way with out the django function.
Here is the views.py if it helps as well:
#ensure_csrf_cookie
def dashboard(request):
return render(request, 'testingland/dashboard.html')
class user_playlist(ListView):
template_name = 'testingland/playlist.html'
context_object_name = 'playlist'
model = UserVenue
def get_queryset(self):
venue = self.request.GET.get('venue', None)
list = self.request.GET.get('list', None)
return UserVenue.objects.filter(list__user=self.request.user)
You don't need to send json type data. So, just removing the line should work fine:
$.ajax({
type: "GET",
url : '/electra/playlist',
// dataType: "json", ---> Remove this line
data: {
'venue': 'venue',
'list': 'list',
},
success: function(data){
$("#playlist").html(data);
console.log(data)
},
failure: function(errMsg) {
alert(errMsg);
}
});
});
Note:- "Deprecation Notice: The jqXHR.success(), jqXHR.error(), and jqXHR.complete() callbacks are removed as of jQuery 3.0. You can use jqXHR.done(), jqXHR.fail(), and jqXHR.always() instead." - jQuery