How to load locally stored images conditionally in Vuejs? - javascript

<template>
<div>
<div v-if="item">
<h1>Price: {{ item.email }}</h1>
<v-if item.email=="john#gmail.com">
<img :src="../"/>
</v-if>
</div>
</div>
</template>
<script>
import { routerid } from "./routerid";
export default {
name: "User",
components: {},
data() {
return {
item: [],
};
},
mounted() {
this.loadData();
},
computed: {
routeId() {
return this.$route.params.id;
},
},
watch: {
routeId() {
console.log("Reload (route change)");
this.loadData();
},
},
methods: {
loadData() {
console.log("Reloading, ID", this.routeId);
if (!this.routeId) return;
routerid(this.$route.params.id).then((item) => {
this.item = item.data;
});
},
},
};
</script>
How to load locally stored images conditionally in Vuejs?
I have three images stored inside of my assets folder. as below.
Now in frontend i want to call them conditionally like for example (if ---> john#gmail.com show the john image stored inside of assets folder. Else no. Similarly for other images too. Like derk and Kate...
Do i need to write if else condition. To load the images based on email? Or any other way to do that?
Code:- https://codesandbox.io/s/combined-logic-api-forked-nzzzwc?file=/src/components/User.vue
api response:- https://fakestoreapi.com/users/1
{"address":{"geolocation":{"lat":"-37.3159","long":"81.1496"},"city":"kilcoole","street":"new road","number":7682,"zipcode":"12926-3874"},"id":1,"email":"john#gmail.com","username":"johnd","password":"m38rmF$","name":{"firstname":"john","lastname":"doe"},"phone":"1-570-236-7033","__v":0}
Note:- email will be different for each id.

First. I think you should provide image link on your API Response (so you should add image link column on your database table). Or if you insist, based on your case, you can use this:
<div v-if="item">
<h1>Price: {{ item.email }}</h1>
<img :src="getPic(item.email)"/>
</div>
and in your method:
getPic(src) {
return "#/assets/" + src.substring(0, src.lastIndexOf("#")) + ".png"
}
But I still really think you should store iamge link in your database

Related

When data is passed from pages to layouts, it is rendered on the client side

I'm using Nuxt.js#2.15.8.
When passing data retrieved with asyncData to layouts, is there a way to render the passed data on the server side?
I was able to pass data from pages to layouts and display the data in LAYOUTS using the following method, but it was CSR.
/pages/index.vue
<script>
export default {
name: 'IndexPage',
layout: 'index',
async asyncData({ $api }) {
const { data } = await $api.fetchData() // data = 'foo'
return { data }
},
created() {
this.getData()
},
methods: {
getData() {
this.$nuxt.$emit('getData', this.data)
},
},
}
</script>
/layouts/index.vue
<template>
<div>
<Nuxt />
<p>{{ data }}</p>
</div>
</template>
<script>
export default {
data() {
return { data: '' }
},
created() {
this.$nuxt.$on('getData', this.setData)
},
methods: {
setData(data) {
this.data = data
},
},
}
</script>
Since it is a CSR, the screen will show empty data for a moment.
Is there any way to avoid CSR when passing data in $emit?
If not, I would like to know how to pass data from pages to layouts without using $emit.

Vue.js - Watch changes in JSON file

Here idea is to watch changes made in JSON file and if some value is changed it automatically changes the condition v-if.
<div id="app">
<div v-if="content == 'one'">
<p>Content one</p>
</div>
<div v-else-if="content == 'two'">
<p>Contentn two</p>
</div>
</div>
Now the tricky part comes, I need to be able after build to change the JSON file, and automatically to change what will be shown.
new Vue({
el: "#app",
data: {
content: ''
},
methods: {
// import of JSON and value that will assign value to this.content
// Now value can be 'one' or 'two'
}
})
Its not possible to watch for changes inside a json file.
What you could do is set the json to a reactive property and check for changes on there.
When changing the JSON you also need to update the reactive property so the watcher gets triggered
new Vue({
el: "#app",
data: {
content: ''
},
watch: {
content: function (val) {
// do something when content has changed
},
},
methods: {
importJson() {
// import json and set contents to content
},
saveJson(newJSON) {
this.content = newJSON
// Somehow save the json data to the json file
}
}
})
You should now that changes to a JSON file are not persistent.
I solve this issue with axios. :)
methods: {
updateData () {
axios.get('../static/client/data.json').then(response => {
console.log(response.data)
this.dataClient = response.data
})
}
},
created () {
this.updateData()
}
Now when you change JSON file in 'dist' folder after build and refresh browser it will load new value.

Laravel 5: show comments using Vue.js

I am creating blog commenting system, I want to show comments for a post using vue.js.
In console, it says
Property or method "comment" is not defined on the instance but
referenced during render.
Also, when I try to catch user name, I got this error
Error in render: "TypeError: Cannot read property 'user' of undefined"
I want to show comments and users who commented to a particular post
in show.blade.php.
web.php
Route::get('results/{post}', 'ResultsController#show')->name('posts.show');
ResultsController
public function show(Post $post)
{
$recommended_posts = Post::latest()
->whereDate('date','>',date('Y-m-d'))
->where('category_id','=',$post->category_id)
->where('id','!=',$post->id)
->limit(7)
->get();
$posts['particular_post'] = $post;
$posts['recommended_posts'] = $recommended_posts;
//return $post->comments()->paginate(5); it returns objects
return view('posts.show',compact('posts'));
}
Comments.vue
<div class="reply-comment" :v-for="comment in comments">
<div class="user-comment" >
<div class="user">
<!--<img src="" alt="" >-->
<avatar :username="comment.user.name" :size="30" ></avatar>
</div>
<div class="user-name">
<span class="comment-name">{{ comment.user.name }}</span>
<p> {{ comment.body }} </p>
</div>
</div>
<div class="reply">
<div class="seemorecomments">
see more
</div>
<button class="reply-button">
<i class="fas fa-reply"></i>
</button>
</div>
</div>
<script>
import Avatar from 'vue-avatar'
export default {
props: ['post'],
components: {
Avatar
},
mounted() {
this.fetchComments()
},
data: () => ({
comments: {
data: []
}
}),
methods: {
fetchComments() {
axios.get(`/results/${this.post.id}`).then(({ data }) => {
this.comments = data
})
}
}
}
show.blade.php
<comments-component :post="{{ $posts['particular_post']->comments }}"></comments-component>
migration table
Schema::create('comments', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('user_id');
$table->integer('post_id');
$table->text('body');
$table->integer('comment_id')->nullable();
$table->timestamps();
});
comment.php, I have this.
protected $with = ['user'];
You have a couple of minor issues with your Vue file that can be addressed pretty quickly.
First, you should define comments as an empty array — a collection will be returned as an array of objects to the Vue. By adding an unnecessary data property in the beginning, you are allowing the v-for loop to run in your template before the data has been retrieved.
EDIT: I'm not sure about the way you wrote this data function, so I have re-written it a way in which I'm familiar.
data() {
return {
comments: []
}
},
Second, you want to get the correct data from the response. Axios data is stored another level deep (response.data). Of course, if you are paginating the results, they are one more level deep (response.data.data).
fetchComments() {
axios.get(`/results/${this.post.id}`).then(response => {
this.comments = response.data
// or for paginated results
// this.comments = response.data.data
})
}
EDIT: Thank you for providing the Gist! I think I'm seeing things more clearly now.
Update your controller like so:
You want to load the comments into the post here.
public function show(Post $post)
{
$recommended_posts = Post::latest()
->whereDate('date','>',date('Y-m-d'))
->where('category_id','=',$post->category_id)
->where('id','!=',$post->id)
->limit(7)
->get();
// load the post comments here
$post->load('comments');
$posts['particular_post'] = $post;
$posts['recommended_posts'] = $recommended_posts;
return view('posts.show',compact('posts'));
}
And you blade like so:
Your module wants a single post, not an array of comments.
<comments-component :post="{{ $posts['particular_post'] }}"></comments-component>
And you Vue like so:
You don't actually need to use Axios at all since we've already loaded the comments.
<script>
import Avatar from 'vue-avatar'
export default {
props: ['post'],
components: {
Avatar
},
data() {
return {
comments: this.post.comments
}
},
}
</script>

Passing Parameter in Vue.js

I am trying to pass a parameter in my Vue.js project, but having no luck. The goal is when I select a user from a list, it should route to that specific user's profile as localhost:61601/Profile/"lastName"
Here is my method when I click next to the users name:
editItem(lastName) {
this.$router.push({ name: 'GetInquiry', params: { lastName: lastName } })
this.$http.get('http://localhost:61601/api/' + 'GetInquiry/' + { lastName : lastName })
},
async GetAllInquiries() {
this.loading = true
try {
this.records = await api.GetAllInquiries()
} finally {
this.loading = false
}
},
As of right now, I am just passing the lastName, but eventually, it will pass a unique id.
Here is the test Profile Page, Here I am just trying to get that users information to display to test the page. So if everything works, the users firstName should display:
<template>
<div class="Profile">
<div class="container">
<div class="row">
<template slot="items" slot-scope="records">
<h1> Student Name: {{ records.items.firstName }}</h1>
</template>
</div>
</div>
<script>
import api from '../../store/api.js'
export default {
data() {
return {
records: {},
}
},
async created() {
this.GetInquiriesByUser()
},
methods: {
async GetInquiriesByUser() {
this.loading = true
try {
this.records = await api.GetInquiriesByUser()
} finally {
this.loading = false
}
},
}
}
</script>
Here is my routes.js
{
path: '/Profile/:lastName',
name: 'GetInquiry',
component: Profile
}
When i open dev tools on chrome, I get
localhost:61601/api/GetInquiry/[object%20Object]
Im using .netcore api for the backend, which gets results as expected, just cannot seem to get it up on my frontend.
If someone can help me and point me to the right direction that would be awesome. Please do let me know if anyone needs more details.
You are passing an object on the vue-resource instead of the value.
Just pass directly the lastname into the route and it should work as fine.
this.$http.get(`http://localhost:61601/api/GetInquiry/${lastName}`);

How to get the latest data from parent to child components after page refresh

I am working on a project and using Vue.js for the frontend. I have following code in the main.js file.
new Vue({ // eslint-disable-line no-new
//el: '#app',
router,
data () {
return {
friends: []
}
},
methods: {
getFriends: function () {
return this.friends;
}
},
created: function () {
this.$http.get('/user/' + this.getUserIDCookie('userID') +
'/friends').then(function (response) {
this.friends = response.data;
});
},
components: {
'nav-bar': require('./components/Navigation.vue')
},
template: `
<div id="app">
<nav-bar></nav-bar>
<router-view class="router-view"></router-view>
</div>`
}).$mount('#app');
In one of the pages(for ex. when the page is redirected to localhost/#/user/1/details, I am retrieving the friends' list from main.js like below:
<script type="text/babel">
export default {
name: 'profile',
data: function () {
return {
user: {},
friends: []
}
},
methods: {
// Some methods
},
created: function () {
this.friends = this.$root.getFriends();
}
}
</script>
The problem arises when I refresh the current page. After page refresh, this.friends is null/undefined because this.$root.getFriends() is returning null/undefined. I can move it to user component, but I want to keep it in main.js so that GET call is used once and data will be available to the whole application.
Any input regarding how to solve this issue would be great. I am using Vue 2.0.1
Really, what you want to do, is pass the data the component needs as props.
The dirt simple easiest way to do it is this.
<router-view class="router-view" :friends="friends"></router-view>
And in your profile component,
export default {
props:["friends"],
name: 'profile',
data: function () {
return {
user: {},
friends: []
}
},
methods: {
// Some methods
}
}
If you want to get more sophisticated, the later versions of VueRouter allow you to pass properties to routes in several ways.
Finally, there's always Vuex or some other state management tool if your application gets complex enough.
The problem is that when you refresh the page, the whole app reloads, which includes the get, which is asynchronous. The router figures out that it needs to render details, so that component loads, and calls getFriends, but the asynchronous get hasn't finished.
You could work around this by saving and pulling the Promise from the get, but Bert's answer is correct: the Vue Way is to send data as props, not to have children pull it from parents.

Categories