How to the Clicked image ID in Vuejs - laravel

I loop and display the images from the database. Every image has a unique ID and I want to get the ID when an image is clicked.
<div v-for="kudo in catkudo" style="width:20%;float:left;display:block;height:80px;">
<div class="kudos_img" style="">
<img style="width:40%" v-bind:value="kudo.id" v-on:click="select($event)" v-model="kudocat" :src="'/kudosuploads/badges/'+kudo.image" alt="">
<p>{{ kudo.catname }}</p>
</div>
</div>
addKudoPost: function(profile_id){
var formkudodata = new FormData();
formkudodata.append('kudodescription', this.kudodescription);
formkudodata.append('kudouser', this.selected);
formkudodata.append('kudoimage', this.kudocat);
axios.post('/addNewsFeedKudoPost', formkudodata)
.then(response=>{
if(response.status===200){
this.posts = response.data.posts;
this.birthdays = response.data.birthdays;
console.log(this.kudodescription);
console.log(this.selected);
$('#post-box')[0].innerHTML = "";
this.newsfeedPostImages();
}
})
.catch(function (error) {
console.log(error);
});
},
I need to get the ID and assign it to a variable when the image is clicked.

Your select method has to have kudo.id as parameter.
<template>
<div v-for="kudo in catkudo" style="width:20%;float:left;display:block;height:80px;">
<div class="kudos_img" style="">
<img style="width:40%" :value="kudo.id" #click="select(kudo.id)" v-model="kudocat" :src="'/kudosuploads/badges/'+kudo.image" alt="">
<p>{{ kudo.catname }}</p>
</div>
</div>
</template>
export default {
methods: {
select (id) {
console.log(id, 'is selected');
}
}
}

v-on:click="select($event, kudo.id)"
If your kudo indeed has an id, then this will work. And you need to modify select to take in said id.

Related

using axios data from Laravel pagination array

ok I am stumped and I know its going to be something stupid. So let me explain more in detail. The code above is what I believe should work for pagination from a Laravel controller to a vue component. I get that I am not fully accounting for pagination and I can handle that later but the first results are not available for use when I do this and I do not understand where my syntax is wrong.
Vue:
<ul role="list" class="space-y-4">
<li
v-for="item in allActivities"
:key="item.id"
class="bg-gray-800 px-4 py-6 shadow sm:p-6 sm:rounded-lg"
>
{{ item.description }}
</li>
</ul>
Mounted:
mounted() {
axios
.get("/activity")
.then((response) => (this.allActivities = response.data));
},
Controller
public function index()
{
$activity = Activity::paginate(10);
return $activity;
}
If in the v-if I change it to allActivities.data it refreshes to show the data until I reload the page and get id not found.
If I change the axios to response.data.data it works, but I lose pagination.
IM stuck
response.data is the result from laravel
response.data.data if the data key in the result which is a list of your models
response.data will contain these keys if using
current_page
data
first_page_url
from
last_page
last_page_url
links
next_page_url
path
per_page
prev_page_url
to
total
I did not fully understand the problem. If you want to change page, send the value of the page you want to display to the fetchActivities() method.
EDIT!
<script>
export default {
data() {
return {
allActivities: {
data: [],
total: null
}
}
},
methods: {
async fetchActivities(page = 1){
const {data:activities} = await axios.get(`/activity?page=${page}`)
this.allActivities.data.push(activities.data)
this.allActivities.total = activities.total
}
},
created() {
this.fetchActivities()
}
}
</script>
<template>
<div v-if="allActivities.data.length > 0">
<ul role="list" class="space-y-4">
<li
v-for="(item, index) in allActivities.data"
:key="index"
class="bg-gray-800 px-4 py-6 shadow sm:p-6 sm:rounded-lg"
>
{{ item.description }}
</li>
</ul>
</div>
</template>

Is there a way to NOT refresh the Page after Updating the data? Laravel 8 and Vue

How can I not refresh or reload the page after updating the data?
I am using Modal to edit the data but the problem is the page still refresh after saving it, is there another way around to fix this concern?
<button class="btn btn-warning" #click="edit(item)"><i class="fa fa-edit"></i></button>
Modal:
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Employee Edit</h5>
</div>
<div class="modal-body">
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" v-model="formEdit.name">
</div>
......
Script: (edit is used to show the data and update is used to update the data)
edit(item){
const vm = this;
vm.formEdit.name = item.name;
vm.formEdit.address = item.address;
vm.formEdit.position = item.position;
this.selectedId = item.id;
$('#editModal').modal('show');
},
update(){
const vm = this;
axios.put(`/employees/${vm.selectedId}`, this.formEdit)
.then(function (response){
alert('Employee Updated')
location.reload();
})
.catch(function (error){
console.log(error);
});
}
This is for Laravel 8 and Vue
employees component:
props: ['employee'],
data() {
return {
employeeList: this.employee,
form:{
name: null,
address: null,
position: null
},
formEdit:{
name: null,
address: null,
position: null
},
selectedId: null
}
}
Please next time add all relevant code to let us know what are you trying to achieve.
First of all, please note that data provided from props should not be mutated because of an anti-pattern. Said that you have to create a deep copy within your component in order to change its content.
Assuming that you are working in just 1 component, where you have your table listing all employees, you can do something like this.
<template>
<div>
<table>
<tr v-for="item in employeeList" :key="item.id">
<td>name: {{ item.name }}</td>
<td>address : {{ item.address }}</td>
<td>position : {{ item.position }}</td>
<td><button class="btn btn-warning" #click="edit(item)"><i class="fa fa-edit"></i></button></td>
</tr>
</table>
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Employee Edit</h5>
</div>
<div class="modal-body">
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" v-model="form.name">
</div>
</div>
<div class="modal-footer">
<button class="btn btn-success" #click="update()">Save</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
employee: Array
},
data: () => ({
employeeList: [],
form: {}
}),
mounted () {
// Since changing a props is anti-pattern, we use a local data which can be manipulated
this.employeeList = [...this.employee]
},
methods: {
edit(item){
// Assign the clicked item to form data
this.form = item
$('#editModal').modal('show')
},
update(){
axios.put(`/employees/${this.form.id}`, this.form)
.then(function (response){
alert('Employee Updated')
// Find the employee index in employeeList array
const updatedEmployee = response.data
const index = this.employeeList.findIndex(x => x.id === updatedEmployee.id)
// If employee is found, then proceed to update the array object by using ES6 spread operator
if (index !== -1) {
this.employeeList = [...this.employeeList.slice(0, index), { ...updatedEmployee}, ...this.employeeList.slice(index + 1)]
}
})
.catch(function (error){
console.log(error)
})
}
}
}
</script>
Code is self-explanatory, but just in case I will clarify a little bit:
Because we can not mutate the props employee, we copy the array to local data by using the ES6 spread operator in mounted() hook.
When you click the button to edit an employee, you assign the item to the form data. Now you have the form with all employee data to be shown/changed anywhere.
Once success API response, since you are updating, you look for the array object and replace the whole array to avoid reactivity issues. In case you are adding a new one, you just can push it by doing this.employeeList.push(updatedEmployee)
EDIT: please note that the above code is a suggestion about how to work with a clean code.
Anyway, right to your question, you can update your array in your axios response by doing
.then(function (response){
alert('Employee Updated')
// Find the employee index in employeeList array
const updatedEmployee = response.data
const index = this.employeeList.findIndex(x => x.id === updatedEmployee.id)
// If employee is found, then proceed to update the array object by using ES6 spread operator
if (index !== -1) {
this.employeeList = [...this.employeeList.slice(0, index), { ...updatedEmployee}, ...this.employeeList.slice(index + 1)]
}
})
.catch(function (error){
console.log(error)
})
during update remove
location.reload();
and add the below code
$('#editModal').modal('hide');
To display data follow the procedure, update data receive from response:
updateStudent(){
axios.put('update_student',{
id:this.id,
name:this.editname,
email:this.editemail,
phone:this.editphone,
})
.then(response=>console.log(response));
axios.get('all_students')
.then(response => {
this.data = response.data;
});
},
You can display the updated data like the below code:
<tr v-for="row in data">
<th scope="row">1</th>
<td>{{ row.name }}</td>
</tr>
Let's create an item in data to assign the value we get from props. Next, let's assign props data to the created element.
The page refresh issue will be resolved.

displaying laravel show method on vue component

i have a list of movies am trying to display the details of one movie using the show method
here is my component for all movies
<template>
<div>
<el-row :gutter="10">
<el-col :span="6" v-for="movie in movies" v-bind:key="movie">
<el-card shadow="always" :body-style="{ padding: '0px'} ">
<img v-bind:src="movie.cover_photo" class="image" >
<div style="padding: 14px;">
<div class="bottom clearfix">
<router-link :to="{name:'details',params:{id:movie.id}}">{{movie.title}}</router-link>
<router-view></router-view>
<h4>{{ movie.year }}</h4>
<h4>{{ movie.type }}</h4>
</div>
<div class="block">
<el-rate :max="10" ></el-rate>
</div>
</div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
movies: [],
movie:{
id:'',
}
};
},
created(){
this. fetchMovieList();
this.showMovie
},
methods: {
fetchMovieList() {
axios.get('/movies').then(response => {
this.movies = response.data;
})
.catch(error=>console.log(error))
},
showMovie(id){
axios.get('/movies/'+id).then((res)=>{
if(res.data.status==true){
this.movie= res.data.movie;
console.log(res.data.movie)
}else{
alert('No Movie founded with this id')
}
})
.catch((err)=>{alert('error')})
}
}
}
</script>
<style scoped>
.image {
width: 100%;
display: block;
}
</style>
my show method:
public function show($id)
{
$movie=Movie::find($id);
if($movie){
return response()->json(['status'=>true,'movie'=>$movie]);
}else{
return response()->json(['status'=>false]);
}
}
my router on app.js:
const movie=Vue.component('details', require('./components/DetailsComponent.vue').default);
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
const router=new VueRouter({
mode:'history',
routes:[
{
path:'/movie/:id',
name:'movie',
component:movie
},
],
});
const app = new Vue({
el: '#app',
router,
});
when i click on the router link it just changes the url to the id of the movie but it doesnt show the component with details when i hit the show endpoint with a specific id it returns the movie in json format on the browser
I think your variable of v-for conflict with the same variable of data().
You should try another variable name of v-for.
Something like
<el-col :span="6" v-for="value in movies" v-bind:key="movie">
<el-card shadow="always" :body-style="{ padding: '0px'} ">
<img v-bind:src="value.cover_photo" class="image" >
<div style="padding: 14px;">
<div class="bottom clearfix">
<router-link :to="{name:'details',params:{id:value.id}}">{{value.title}}</router-link>
<router-view></router-view>
<h4>{{ value.year }}</h4>
<h4>{{ value.type }}</h4>
</div>
<div class="block">
<el-rate :max="10" ></el-rate>
</div>
</div>
</el-card>
</el-col>
Hope this helps you: Reacting to Params Changes
Regards,

Owl carousel spits out a single item instead of a carousel

I am trying to make a carousel that shows a list of new tutors in a specific area from latest first. I am using laravel 5.6, vue.js and owl carousel.
Below I am using axios to retrieve from the database, and call owl-carousel
<script>
export default {
props: {
areaId: null,
},
data () {
return {
NewTutors: {}
}
},
methods: {
getNewTutor () {
var that = this;
axios.get( '/' + this.areaId + '/home/new').then((response) => {
that.NewTutorss = response.data;
})
.catch(error => {
console.log(error)
this.errored = true
});
}
},
mounted () {
this.getNewTutor();
}
}
$(document).ready(function() {
$('#NewHustles').owlCarousel();
});
</script>
and here and try and loop through each new tutor in a carousel.
<div class="owl-carousel owl-theme owl-loaded" id="NewTutors">
<div class="owl-stage-outer">
<div class="owl-stage">
<div class="owl-item" v-for="NewTutor in NewTutors>
<div class="card">
<div class="card-header">
{{NewTutor.name}}
</div>
<div class="card-body">
<div>
{{NewTutor.area.name}}
</div>
<div>
Image goes here
</div>
<div>
{{NewTutor.user.first_name}}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
I get all the cards, with the correct data passed through, but instead of a single row carousel, I get a big blob of cards that move as if there was only one item. I have tried Vue.nexttick, and playing around with a few other things, but nothing seems to work quite right.
Thank you for your help.

(Vue.js and Laravel) Array won't refresh after deleting item

I'm new to Vue.js, trying to create a single page blog just to get my feet wet with the vue/laravel combo, and I am stuck when it comes to deleting a "story" from the array of "stories" I am working with. I know the routes are fine because the story actually deletes, no errors are thrown, but the deleted story will remain in the array until I refresh the page. From what I've read elsewhere, the code I have implemented should update the array immediately. I have attached the relevant parts of my blade view, vue.js file, and controller. Thanks in advance!
JS (VUE)
new Vue({
el: '[vue-news]',
search: "",
data: {
stories: ''
},
ready: function() {
// GET request
this.$http.get('/app/news/get', function(data, status, request) {
// set data on vm
this.$set('stories', data);
// console.log(data);
}).error(function(data, status, request) {
// handle error
});
},
methods: {
// DELETE STORY FROM ARRAY
deleteNews: function(id, index) {
this.$http.delete('app/news/' + id + '/delete').success(function(response) {
this.stories.$remove(index);
swal("Deleted!", "Your news story has been deleted.", "success");
}).error(function(error) {
console.log(error);
swal(error);
});
}
}
});
BLADE
<section vue-news>
<div class="row news-row">
<div class="columns large-9 medium-9 small-12">
<article data-id="#{{ story.id }}" class="story panel" v-for="story in stories | filterBy search" track-by="$index">
<h1>#{{ story.title }}</h1>
<p>#{{ story.content }}</p>
<p>#{{ story.created_at }}</p>
<p>#{{ story.id }}</p>
<p>#{{ story.timestamp }}</p>
Read More...
<div class="options">
<a #click="editNews" href="#">
<i class=" edit fa fa-pencil-square-o"></i>
</a>
{{-- DELETE NEWS BUTTON --}}
<a #click.prevent="deleteNews(story.id, $index)" href="#">
<i class="delete fa fa-trash-o"></i>
</a>
</div>
</article>
</div>
<div class="columns large-3 medium-3 small-12">
<input type="text" v-model="search">
</div>
</div>
</section>
CONTROLLER
public function delete($id)
{
return response()->json(News::destroy($id));
}
The $remove method now treats the argument as an item to search for rather than an index. In other words, try this out:
Delete method:
deleteNews: function(id, story) {
this.$http.delete('app/news/' + id + '/delete').success(function(response) {
this.stories.$remove(story);
swal("Deleted!", "Your news story has been deleted.", "success");
}).error(function(error) {
console.log(error);
swal(error);
});
}
HTML section:
<a #click.prevent="deleteNews(story.id, story)" href="#">
<i class="delete fa fa-trash-o"></i>
</a>
Source: https://github.com/vuejs/vue/releases
Edit: Since you are passing the entire story item, you can actually just pass one argument and shorten the code to this:
Vue:
deleteNews: function(story) {
this.$http.delete('app/news/' + story.id + '/delete').success(function(response) {
this.stories.$remove(story);
swal("Deleted!", "Your news story has been deleted.", "success");
}).error(function(error) {
console.log(error);
swal(error);
});
}
HTML:
<a #click.prevent="deleteNews(story)" href="#">
<i class="delete fa fa-trash-o"></i>
</a>

Resources