displaying laravel show method on vue component - laravel

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,

Related

infinite scroll using laravel and vue request not sent to display data

good day;
i new in vue.js
i have simple problem when i using infinite scroll i make configuration as below but when page reloaded it must send request to data base to show data when page =1 this request not sent
i want help to get it work
this is my
this is service component
<template>
<div>
<!-- start covr-page --------------------- -->
<div class="covr-page">
<h2>خدمات لوجستية متكاملة </h2>
<div class="overlay"></div>
</div>
<!-- end covr-page --------------------- -->
<!-- start servic --------------------- -->
<div class="servic sections">
<div class="container">
<h3 class="start-title">
<img src="/images/start-title.png" alt="">
خدمات لوجستية متكاملة
</h3>
<div class="row">
<div v-for="service,key in list" class="col-lg-offset-3 col-lg-6 col-md-12 col-md-8 col-sm-offset-1 col-sm-10">
<a href="order-service.html">
<div class="email-signature">
<div class="signature-details">
<div class="signature-img">
<img :src="`upload/${service.icon}`" alt="">
</div>
</div>
<div class="contant-serv">
<h4>{{service.ar_name}}</h4>
<p>
{{service.ar_description}}
</p>
</div>
</div>
</a>
</div>
<infinite-loading #distance="100" #infinite="infiniteHandler"></infinite-loading>
</div>
</div>
</div>
</div>
</template>
this is my route
Route::get('/Services', 'ServicesController#Services');
this is my js code
<script>
export default {
name: "Services",
data: function () {
return {
list: [],
page:1
}
},
mounted(){
// this.infiniteHandler()
// axios.get('/Services')
// .then((response) =>{
// this.list=response.data
// }).catch((error) =>this.errors=error.response.data.errors );
},
methods: {
infiniteHandler($state) {
this.$http.get('/Services?page='+this.page)
.then(response => {
return response.json();
}).then(data => {
$.each(data.data, (key, value)=> {
this.list.push(value);
});
$state.loaded();
});
this.page = this.page + 1;
},
},
}
</script>
you have not declared vue-infinite-loading
import InfiniteLoading from 'vue-infinite-loading';
export default {
components: {
InfiniteLoading,
},

How can I put an Image for a specific user in vuejs template?

I'm actually working on profile picture for users.
I now want to put this profil picture next to their name in my chat which is working with pusher and vuejs.
My img is like this :
<img class="profil_pic" src="{{url('uploads/logo_'.Auth::user()->firstName."_".Auth::user()->lastName.".png")}}" onerror="this.src='images/user.jpg'" alt="">
I can not just past it in the file it's not working and it would be for every user, but I want it to be for the auth user. I'm kinda new to vue.js any help would be thankful.
This is my chatMessage.vue :
<template>
<ul class="chat messages" >
<li class="clearfix list-group-item" v-for="message in messages" v-bind:class="{
classForUser: (message.user.id === currentuserid),
classForNotUser: (message.user.id !== currentuserid)}" >
<div class="chat-body clearfix" >
<div class="header">
<strong class="primary-font"
v-bind:class="{
classForAuthorSameAsUser: (message.user.id === currentuserid),
classForAuthorDiffThanUser: (message.user.id !== currentuserid)
}">
{{ message.user.firstName }}
{{ message.user.lastName}}
:
</strong>
{{ message.human_readable_time}}
</div>
<p>{{ message.message }}</p>
</div>
</li>
</ul>
</template>
<script>
export default {
props: ['messages','currentuserid']
};
</script>
<style scoped>
.classForAuthorSameAsUser {
color: lightseagreen ;
}
.classForAuthorDiffThanUser {
color: black;
}
.classForUser{
width: 70%;
left: 30%;
}
.classForNotUser{
width: 70%;
}
</style>
And this is the html of my chat :
<div class="row">
<div class="col-md-12 col-md-offset-2">
<div class="col-md-12 col-md-offset-2">
<div class="panel-body panel-content" id="mess_cont" :userid="{{Auth::user()->id}}">
<chat-messages id="mess" :messages="messages" :currentuserid="{{Auth::user()->id}}"></chat-messages>
</div>
<div class="panel-footer">A
<chat-form
v-on:messagesent="addMessage"
:user="{{ Auth::user() }}">
</chat-form>
</div>
</div>
</div>
</div>
I think I have to use again the thing that help me to get the user id, but I don't really know how it works with vue.js.
Thanks for your time
And now I have this :
<template>
<ul class="chat messages" >
<li class="clearfix list-group-item" v-for="message in messages" v-bind:class="{
classForUser: (message.user.id === currentuserid),
classForNotUser: (message.user.id !== currentuserid)}" >
<div class="chat-body clearfix" >
<div class="header">
<strong class="primary-font"
v-bind:class="{
classForAuthorSameAsUser: (message.user.id === currentuserid),
classForAuthorDiffThanUser: (message.user.id !== currentuserid)
}">
<img class="profil_pic" :src="`path/to/uploads/logo_${user.firstName}_${user.lastName}.png`" alt="Auth image"/>
{{ message.user.firstName }}
{{ message.user.lastName}}
:
</strong>
{{ message.human_readable_time}}
</div>
<p>
{{ message.message }}
</p>
</div>
</li>
</ul>
</template>
<script>
export default {
props: ['messages','currentuserid'],
data() {
return {
user: null,
}
},
methods: {
this:$http.get('/api/get-auth')
.then((response) => {
this.user = response.data.auth
})
.catch((error) => {
// handle error
}),
}
};
</script>
<style scoped>
.classForAuthorSameAsUser {
color: lightseagreen ;
}
.classForAuthorDiffThanUser {
color: black;
}
.classForUser{
width: 70%;
left: 30%;
}
.classForNotUser{
width: 70%;
}
</style>
And it's not working
As I see, what you want to achieve is to take this img tag (with blade's logic):
<img class="profil_pic" src="{{url('uploads/logo_'.Auth::user()->firstName."_".Auth::user()->lastName.".png")}}" onerror="this.src='images/user.jpg'" alt="">
And put it inside your chatMessage.vue component. If that's it, you can do so like this:
1. Create a function inside a controller in order to return the authenticated user information:
public function getAuth()
{
return response()->json([
'auth' => auth()->user(),
], 200);
}
2. Create a new route in order to get that information inside your api.php file:
Route::get('/get-auth', 'YourController#getAuth');
3. Create a new param inside the data() returned object in the chatMessage.vue component:
data() {
return {
user: null,
}
},
4. Create a method inside your chatMessage.vue component with the necessary code to fetch that data:
fetchAuth() {
this.$http.get('/api/get-auth')
.then((response) => {
this.user = response.data.auth
})
.catch((error) => {
// handle error
});
}
5. Call that method inside your created() life cycle method:
created() {
this.fetchAuth();
}
6. Create the img tag like this:
<img class="profil_pic" :src="`path/to/uploads/logo_${user.firstName}_${user.lastName}.png`" alt="Auth image"/>

How can I dynamically nest vue components?

I want to add one component inside other when user clicks a button. but how can we render the component in the virtual dom.
I tried using v-html but its not working.
Whats the best way to solve this issue?
export default {
data(){
return{
elements : {
hotel : '<hotel-form></hotel-form>'
},
}
},
methods:{
addHotel(){
console.log('add');
}
}
}
<template>
<div class="container" style="margin-top:300px;">
<div class="row" id="mainform">
<div v-for="item in elements">
<div v-html="item"></div>
</div>
</div>
<button #click="addHotel()">add hotel</button>
</div>
</template>
I would bind an array (hotels) to a <hotel-form> component tag via v-for. This way, no hotel-form components will be initially rendered, and then you can push an object (with any data to want bound to the hotel-form component) to the hotels array and the DOM will automatically render a new corresponding hotel-form component.
Here's a simple example:
Vue.component('hotel-form', {
template: '#hotel-form',
props: { id: Number, name: String },
});
new Vue({
el: '#app',
data() {
return { hotels: [], count: 0 }
},
methods: {
addHotel() {
this.hotels.push({ name: 'foo', id: this.count++ })
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id="app">
<div id="mainform">
<hotel-form v-for="hotel in hotels" :key="hotel.id" v-bind="hotel">
</hotel-form>
</div>
<button #click="addHotel">add hotel</button>
</div>
<template id="hotel-form">
<div>
<h4>Hotel Form #{{ id }}</h4>
<div>{{ name }}</div>
</div>
</template>

Attempting to load a Vue component and populate it with Ajax json content in Laravel

I am new to Laravel and a complete noob to Vue. I searched many other Laravel/Vue posts but none seemed to be similar enough to get me to a solution. When attempting to load this component on my view I receive the following error
app.js:32654 [Vue warn]: Property or method "features" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
Please let me know what I am missing.
chrome.google.com/webstore/detail/vuejs-devtools/ shows that Vue is loaded
I would like to load data from an ajax call to my vue component. that can be updated on the fly by event handler
App.js
window.Vue = require('vue');
Vue.component('Example', require('./components/Example.vue'));
const app = new Vue({
el : '#app',
});
$(document).ready(function() {
$.ajaxSetup({
headers : {
'X-CSRF-TOKEN' : $('meta[name="csrf-token"]').attr('content')
}
});
})
Example.vue
<template>
<div class="container projects-container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Example Component</div>
<div class="panel-body">
<h1>I'm an example component!</h1>
<ul class="list-group">
<li class="list-group-item" v-for="feature in features">
{{ feature.properties.name }}
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component mounted.')
},
}
</script>
bladefile
<head>
<meta name="csrf-token" content="INMA4kLlG32gfhf4Z3BBGIFxitrVCWzzqgqPfooEj">
// and yes Vue is loaded
</head>
<body>
<div id="app">
<example></example>
</div>
...
<script>
Vue.component('example',{
template: 'Example',
})
//returns the JSON listed below
someOtherObject.addListener('click', function(e) {
$.ajax({
url:json,
method:'GET',
success:function(msg){
app.data = JSON.parse(msg);
}
})
})
</script>
JSON
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"geometry":{
"type":"Point",
"coordinates":[
-117.155083,
33.569672
]
},
"properties":{
"heading":null,
"face":"South",
"status":"1",
"name":"MEADOWLARK ",
"type":"Single Family Home",
"client_id":"26",
"client_name":"Pulte Homes",
"city_name":"French Valley"
}
},
{
"type":"Feature",
"geometry":{
"type":"Point",
"coordinates":[
-117.151390,
33.543981
]
},
"properties":{
"heading":null,
"face":"South",
"status":"1",
"name":"Testing Project",
"type":"Single Family Home",
"client_id":"83",
"client_name":"Testing Account",
"city_name":"Temecula Valley"
}
},
{
"type":"Feature",
"geometry":{
"type":"Point",
"coordinates":[
-117.223720,
33.571522
]
},
"properties":{
"heading":null,
"face":"South",
"status":"1",
"name":"Oak Ridge",
"type":"Single Family Home",
"client_id":"98",
"client_name":"Woodside 05S LP",
"city_name":"Beaumont"
}
}
]
}
The features array must be declared either as a prop or part of the component data.
As a prop:
<template>
<div class="container projects-container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Example Component</div>
<div class="panel-body">
<h1>I'm an example component!</h1>
<ul class="list-group">
<li class="list-group-item" v-for="feature in features">
{{ feature.properties.name }}
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component mounted.')
},
props: ['features']
}
</script>
As component data:
<template>
<div class="container projects-container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Example Component</div>
<div class="panel-body">
<h1>I'm an example component!</h1>
<ul class="list-group">
<li class="list-group-item" v-for="feature in features">
{{ feature.properties.name }}
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component mounted.')
},
data: function() {
return {features: []}
}
}
</script>
If you use a prop, you'll need to bind the prop in the template. If you use component data, you'll need to update the success callback function in the AJAX request to correctly update the data of the component rather than the app as a whole.
Also, beware of the reactivity caveats for loading new data, as outlined in the docs.
EDIT: Full example solution using component data
Here's a working example using a simplified version of your example component. Note that to do this I used the ref attribute so that the component could be addressed directly. Using refs is described in the docs as an "escape hatch" that should only be used when strictly necessary. A better pattern might be an external store, such as Vuex.
Vue.component( "example", {
template: '<div><h1>Example Component!</h1><ul v-if="features.length"><li v-for="feature in features">{{ feature.name }}</li></ul></div>',
data: function() {
return { features : [] }
}
});
var app = new Vue( { el: '#app' });
//A function to represent the AJAX callback
var doMockAjax = function() {
var mockData = [{name: 'One'},{name: 'Two'},{name: 'Three'}];
app.$refs.example.features = mockData;
}
document.getElementById('load-data').addEventListener('click', function(e) {
//This simulates the ajax callback by populating the array asynchronously
setTimeout(doMockAjax,1000);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
<example ref="example"></example>
</div>
<button id="load-data">Load</button>

Getting details from vue component in laravel

I have a Laravel 5.4 project.
I have created two components : Students.vue and Student.vue component
Students.vue get all the students and Student.vue the markup for one display of a student
here is my Students.vue
<template>
<div v-if = "students.length && meta">
<pages :pagination = "meta"></pages>
<div class = "col-lg-3 col-sm-6 col-md-4 music_genre" v-for = "student in students">
<student :student = "student"></student>
</div>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import eventHub from '../../events.js'
export default {
methods: {
...mapActions({
getStudents: 'student/getStudents'
})
},
computed : {
...mapGetters ({
students : 'student/students',
meta : 'student/meta'
})
},
mounted() {
this.getStudents(1)
}
}
</script>
here is my Student.vue
<template>
<div class="">
<div class="team-info ">
<h4>
<a href="#">
{{student.name}} {{student.last_name}}
</a>
</h4>
<span class='team-member-edit'>
<i class='fa fa-pencil icon-xs'></i>
</span>
</div>
<p>Along with studies, is good in all around activities held in the university events.</p>
</div>
</template>
<script>
export default {
props:['student'],
mounted() {
}
}
</script>
When i click on the Student Name, I would like to display all the details of the student. How to achieve that
I assume you have a key differentiating each students, hence you can do this
'/students/:id': {
component: 'student'
}

Resources