How do I pass data to a component using Props in Vue2? - javascript

I have created a .Vue file to feature information on a cafe (Cafe Details Page). However, I would like to take parts of this details page and make it its own component, in order to manage any template updates more efficiently.
Therefore, I have created a Component (CafeHeader.vue) inside a components folder. I am trying to pass down the data from my array (Which is being used on my Cafe Details page) to this component using Props. However, I can't seem to get it to work.
The template for my Cafe Details Page is as below:
<template>
<div>
<div v-for="cafe in activeCafe">
<CafeHeader v-bind:cafes="cafes" />
<div class="content">
<p>{{ cafe.cafeDescription }}</p>
</div>
</div>
</div>
</template>
<script>
import CafeHeader from "./../../components/CafeHeader";
import cafes from "./../../data/cafes"; // THIS IS THE ARRAY
export default {
data() {
return {
cafes: cafes
};
},
components: {
CafeHeader,
},
computed: {
activeCafe: function() {
var activeCards = [];
var cafeTitle = 'Apollo Cafe';
this.cafes.forEach(function(cafe) {
if(cafe.cafeName == cafeTitle){
activeCards.push(cafe);
}
});
return activeCards;
}
}
};
</script>
Then, in a components folder I have a component called CafeHeader where I am wanting to use the data from the array which is previously imported to the Cafe Details page;
<template>
<div>
<div v-for="cafe in cafes">
<h1>Visit: {{cafe.cafeName}} </h1>
</div>
</div>
</template>
<script>
export default {
name: "test",
props: {
cafes: {
type: Array,
required: true
}
},
data() {
return {
isActive: false,
active: false
};
},
methods: {}
};
</script>
If in the CafeHeader component I have cafe in cafes, it does render data from the cafes.js However, it is every cafe in the list and I want just a single cafe.
<template>
<div>
<div v-for="cafe in cafes">
<h1>Visit: {{cafe.cafeName}} </h1>
</div>
</div>
</template>

The component also needed activeCafes on the v-for
<template>
<div>
<div v-for="cafe in activeCafes">
<h1>Visit: {{cafe.cafeName}} </h1>
</div>
</div>
</template>

Related

How to hide content when clicked checkbox from different components in vuejs?

//inputtwo.vue
<template>
<div><input type="checkbox" v-model="checked" />one</div>
</template>
<script>
export default {
name: "inputtwo",
components: {},
data() {
return {};
},
};
</script>
//maincontent.vue
<template>
<div>
<div class="container" id="app-container" v-if="!checked">
<p>Text is visible</p>
</div>
<common />
</div>
</template>
<script>
export default {
name: "maincontent",
components: {},
data() {
return {
checked: false,
};
},
methods: {
hidecont() {
this.checked = !this.checked;
},
},
};
</script>
//inputone.vue
<template>
<div><input type="checkbox" v-model="checked" />one</div>
</template>
<script>
export default {
name: "inputone",
components: {},
data() {
return {};
},
};
</script>
How to hide content of checkbox from different components in Vuejs
I have three components called inputone(contains checkbox with v-model),inputtwo (contains checkbox with v-model),maincontent.(having some content and logic), So when user click on checkboxes from either one checckbox(one,two). i schould hide the content.
Codesanfdbox link https://codesandbox.io/s/crimson-fog-wx9uo?file=/src/components/maincontent/maincontent.vue
reference code:- https://codepen.io/dhanunjayt/pen/mdBeVMK
You are actually not syncing the data between components. The main content checked never changes. You have to communicate data between parent and child components or this won't work. And try using reusable components like instead of creating inputone and inputtwo for same checkbox create a generic checkbox component and pass props to it. It is a good practice and keeps the codebase more manageable in the longer run.
App.vue
<template>
<div id="app">
<maincontent :showContent="showContent" />
<inputcheckbox text="one" v-model="checkedOne" />
<inputcheckbox text="two" v-model="checkedTwo" />
</div>
</template>
<script>
import maincontent from "./components/maincontent/maincontent.vue";
import inputcheckbox from "./components/a/inputcheckbox.vue";
export default {
name: "App",
components: {
maincontent,
inputcheckbox,
},
computed: {
showContent() {
return !(this.checkedOne || this.checkedTwo);
},
},
data() {
return {
checkedOne: false,
checkedTwo: false,
};
},
};
</script>
checkbox component:
<template>
<div>
<input
type="checkbox"
:checked="value"
#change="$emit('input', $event.target.checked)"
/>
{{ text }}
</div>
</template>
<script>
export default {
name: "inputcheckbox",
props: ["value", "text"],
};
</script>
Content:
<template>
<div class="container" id="app-container" v-if="showContent">
<p>Text is visible</p>
</div>
</template>
<script>
export default {
name: "maincontent",
props: ["showContent"]
}
</script>
https://codesandbox.io/embed/confident-buck-kith5?fontsize=14&hidenavigation=1&theme=dark
Hope this helps and you can learn about passing data between parent and child components in Vue documentation: https://v2.vuejs.org/v2/guide/components.html
Consider using Vuex to store and maintain the state of the checkbox. If you're not familiar with Vuex, it's a reactive datastore. The information in the datastore is accessible across your entire application.

I am trying to render a random array element from a button click using axios and a local json file. What am I missing?

I have got it now where I can render the entire array in a random order, just cant render one element of the array. I am also having an issue in showing the entire json object instead of just the text of the quote.
here is the html:
<template>
<div>
<button v-on:click="getTeacupData">Get Teacup Data</button>
<!-- <div>{{ teacupDataList }}</div> -->
<div
v-for="teacupData in teacupDataList"
:key="teacupData.quote"
class="teacup-data"
>
<div>
<span class="quote">
{{
teacupDataList[Math.floor(Math.random() * teacupData.quote.length)]
}}</span
>
</div>
</div>
</div>
</template>
and here is the script:
<script>
import axios from 'axios'
export default {
name: 'Teacup',
data() {
return {
teacupDataList: []
}
},
methods: {
getTeacupData() {
axios.get('/teacupProph.json').then((response) => {
this.teacupDataList = response.data
})
}
}
}
</script>
Add a computed property called randomQuote as follows :
<script>
import axios from 'axios'
export default {
name: 'Teacup',
data() {
return {
teacupDataList: []
}
},
computed:{
randomQuote(){
const rand=Math.floor(Math.random() * this.teacupDataList.length)
return this.teacupDataList[rand]?this.teacupDataList[rand].quote:""
}
},
methods: {
getTeacupData() {
axios.get('/teacupProph.json').then((response) => {
this.teacupDataList = response.data
})
}
}
}
</script>
in template don't use v-for loop just call the computed property :
<template>
<div>
<button v-on:click="getTeacupData">Get Teacup Data</button>
<!-- <div>{{ teacupDataList }}</div> -->
<div>
<span class="quote">
{{
randomQuote
}}</span>
</div>
</div>
</template>
Edit
place your json file inside the components folder and call it like axios('./teacupProph.json') and fix the #:click to #click, check this code

How can i change components data in Vue.js?

I am new in Vue.js. i don't know how can i render four message like this
hi
bye
go
back
my result is render go, back. i think my code is not render hello1.vue component.
i want render hello, hello1 components. how can i fix it?
hello.vue
<template>
<P> {{ hello.a }} </p>
<p> {{ hello.b }} </p>
</template>
<script>
export default {
data(){
return{
hello:{
a = "hi",
b = "bye"
}
},
props: ['hello1']
}
</script>
hello2.vue
<template>
<hello-vue :hello="hello1" />
</template>
<script>
import helloVue from './hello.vue'
export default {
data(){
return{
hello1:{
a = "go",
b = "back"
}
},
components:{
'hello-vue': helloVue
}
}
</script>
You are passing the data in a bit of a messy way. So first thing is we need to split this into a parent and child component. The child component will print out your two lines, while parent component will call and pass data.
Secondly in Hello.vue you have props AND data, the template is only accessing hello and not hello1 meaning the props variable isnt parsed.
Thirdly <template> may have only 1 child so that will cause rendering issues as well.
There are different ways, but let's try this
HelloItem.vue
<template>
<div>
<P> {{ hello.a }} </p>
<p> {{ hello.b }} </p>
</div>
</template>
<script>
export default {
data() {
return { }
},
props: ['hello']
}
</script>
And now we call this twice by passing in data
HelloView.vue
<template>
<div>
<hello-item :hello="hello1"/>
<hello-item :hello="hello2"/>
</div>
</template>
<script>
import HelloItem from './HelloItem.vue'
export default {
data() {
return {
hello1:{
a: "hi",
b: "bye"
},
hello2:{
a: "go",
b: "back"
},
}
},
components:{
'hello-item': HelloItem
}
}
</script>
Let me know if this answers your question.

VueJS Routing the same component not triggering OWL Carousel

Hello
I'm facing this problem with re-evaluating the images rendered by VueJS into a Carousel plugin (OwlCarousel) while loading the same component with different variables
the problem is when loading the page with images everything works well and the carousel can show the images, but when clicking on a link to go to the same component with other images, the carousel shows only an empty box.
Here is what I have so far:
<template>
<div>
<div id="owl-work">
<div class="item" v-for="image in project.images" :key="image.id">
<figure><img :src="'uploads/'+image.url" alt=""></figure>
</div>
</div>
<div class="similars" v-for="similar in similars">
<router-link :key="$route.fullPath" :to="{ name: 'project', params: { id: similar.id, project:similar }}" replace>
<h4>{{similar.title}}</h4>
</router-link>
</div>
</div>
</template>
<script>
export default {
props: ["id"],
computed: {
...mapGetters(['getProject', 'getSimilars']),
project() {
return this.getProject(this.id)
},
similars() {
return this.getSimilars(this.id)
}
}
}
$("#owl-work").owlCarousel();
</script>
and my routes look like:
[
{name: 'projects', path: '/projects', component: ProjectsScreen},
{name: 'project', path: '/project/:id', component: ProjectScreen, props: true},
]
So the question is how to load the "similar" project image into the carousel when clicking on the <router-link> which outputs the results in the same components.
PS: the other fields are changed, and when getting rid of the carousel it works, so its certain with the setup of the carousel itself with how VueJS deals with routing or something like that..
Move the owl initialization to a lifecycle hook, so it is executed again when the route changes:
<script>
export default {
props: ["id"],
computed: {
...mapGetters(['getProject', 'getSimilars']),
project() {
return this.getProject(this.id)
},
similars() {
return this.getSimilars(this.id)
}
},
mounted() {
$("#owl-work").owlCarousel();
}
}
// Removed from here
</script>
Or, better yet, remove the need for accessing from id and use a ref instead.
<template>
<div>
<div ref="owlwork">
<div class="item" v-for="image in project.images" :key="image.id">
<figure><img :src="'uploads/'+image.url" alt=""></figure>
</div>
</div>
<div class="similars" v-for="similar in similars">
<router-link :key="$route.fullPath" :to="{ name: 'project', params: { id: similar.id, project:similar }}" replace>
<h4>{{similar.title}}</h4>
</router-link>
</div>
</div>
</template>
<script>
export default {
props: ["id"],
computed: {
...mapGetters(['getProject', 'getSimilars']),
project() {
return this.getProject(this.id)
},
similars() {
return this.getSimilars(this.id)
}
},
mounted() {
$(this.$refs.owlwork).owlCarousel();
}
}
// Removed from here
</script>

Vue.js - Using parent data in component

How I can get access to parent's data variable (limitByNumber) in my child component Post?
I tried to use prop but it doesn't work.
Parent:
import Post from './components/Post.vue';
new Vue ({
el: 'body',
components: { Post },
data: {
limitByNumber: 4
}
});
Component Post:
<template>
<div class="Post" v-for="post in list | limitBy limitByNumber">
<!-- Blog Post -->
....
</div>
</template>
<!-- script -->
<script>
export default {
props: ['list', 'limitByNumber'],
created() {
this.list = JSON.parse(this.list);
}
}
</script>
Option 1
Use this.$parent.limitByNumber from child component. So your Component template would be like this
<template>
<div class="Post" v-for="post in list | limitBy this.$parent.limitByNumber" />
</template>
Option 2
If you want to use props, you can also achieve what you want. Like this.
Parent
<template>
<post :limit="limitByNumber" />
</template>
<script>
export default {
data () {
return {
limitByNumber: 4
}
}
}
</script>
Child Pots
<template>
<div class="Post" v-for="post in list | limitBy limit">
<!-- Blog Post -->
....
</div>
</template>
<script>
export default {
props: ['list', 'limit'],
created() {
this.list = JSON.parse(this.list);
}
}
</script>
If you want to access some specific parent, you can name all components like this:
export default {
name: 'LayoutDefault'
And then add some function (maybe like vue.prototype or Mixin if you need it in all your components). Something like this should do it:
getParent(name) {
let p = this.$parent;
while(typeof p !== 'undefined') {
if (p.$options.name == name) {
return p;
} else {
p = p.$parent;
}
}
return false;
}
and usage could be like this:
this.getParent('LayoutDefault').myVariableOrMethod

Categories

Resources