how can I pass props to child props? (vue.js) - javascript

Hi I'm making vue application and What I want to do is there's parentsComponent which has ChildOne and ChildTwo, the data is getting from same dataArray but childTwo has multiple data. and childTwo has childOneComponent inside. but I want to passed the data to ChildTwo from ParentsComponent and give it to ChildOne again.
is it possible?
ParentsComponent.vue
<template>
<ChildOneComponent :data="NewsData">
<ChildTwoComponent :data="NewsData.sports">
</template>
ChildOneComponent.vue
<div>
{{data.title}}
</div>
ChildTwoComponent.vue
<ChildOneComponent></ChildOneComponent>

It should be as below. You will have to pass the whole Newsdata object to your ChildTwoComponent as you are rendering ChildOneComponent from it.
You can update your template rendering of ChildTwoComponent accordingly.
ParentsComponent.vue
<template>
<div>
<ChildOneComponent :data="NewsData">
<ChildTwoComponent :data="NewsData">
</div>
</template>
ChildTwoComponent.vue
<ChildOneComponent :data="NewsData"></ChildOneComponent>

Related

How to render VueJS Slot in a another component

VueJS slot could be placed anywhere inside a parent component.
However, I have a use case where I need to show a slot in another (foreign) component outside the parent component.
For example, I have component Student:
<template>
<slot name="detail" />
<slot name="status" /> <!-- I don't want to render this slot inside this component, but somewhere else -->
</template>
I want to display the student's status in a header section outside the student component as below:
<div class="Header">
<!-- student status slot should go here-->
<student-status-slot></student-status-slot>
</div>
<div class="InputForm">
<student>
<template #detail>This the detail information about student</template>
<template #status>Grade A</template>
</student>
</div>
You may suggest to create a new "student-status-slot" component. However, the idea is to have all student related information, including "status" declared under the component, but render some of the slot somewhere else.
I have tried another approach creating a separate component and pass the status data via prop. But That is not what I wanted to achieve. I don't want to pass data, but re-use the student status component, which can be dynamic.
In a parent component you can access child's slots by adding ref attribute to child, and then render the VNode obtained. See the demo here https://codesandbox.io/s/happy-einstein-9f5rke?file=/src/components/StudentPage.vue
But actually I wouldn't recommend this way such it's not conventional and slots were not designed for this. I think you should rather consider using portals (Vue 3 portals or https://www.npmjs.com/package/portal-vue if you use Vue 2) to achieve your goal

Cannot dynamically pass a prop to a component within a v-for loop in Vue js

I have an array sheets initialised in data, has an item pushed to it when a button is pressed
data() {
return {
sheets: []
};
}
And in the html I'm trying to add a Card component for each element in this array and pass the data as a prop, but none of the components get rendered and there is no error message. I also tried putting the v-for directly on the component but it has the same result
<div id="sheets">
<template v-for="c in sheets">
<Card :info="c"/>
</template>
</div>
Meanwhile if I do something like this, it displays all the data in the array correctly, so I dont understand whats going wrong here
<div id="sheets">
<template v-for="c in sheets">
<span>{{c}}</span>
</template>
</div>
--
Solution
In my component the data from prop was being manipulated in the created() function, it works after I did this in the mounted() function instead
Make sure you have following things done correctly:
Imported your Card component
Passing and accessing the props
There are no conflicts in the variable names and id names
Next thing you need to know and is a must while using v-for is adding :key to the element which acts as unique id and lets Vue detect that each element is unique inside the v-for. One thing to be noted while using :key is that, you cannot use :key on the <template> tag.
Adding a validation using v-if would be a good idea, so v-for only executes if the array is not empty.
<div id="sheets">
<template v-if="sheets.length">
<Card v-for="(sheet,index) in sheets" :key="index" :info="sheet" />
</template>
</div>
Edit 1: As mentioned by Michal in the comments section that using index can lead to difficulties while debugging issues. You can use either :key="sheet" or if sheet is object including some unique id in it, then use :key="sheet.id" and get rid of the index
// use this if sheet is not an object
<div id="sheets">
<template v-if="sheets.length">
<Card v-for="sheet in sheets" :key="sheet" :info="sheet" />
</template>
</div>
OR
// use this if sheet is an object having some unique id in it
<div id="sheets">
<template v-if="sheets.length">
<Card v-for="sheet in sheets" :key="sheet.id" :info="sheet" />
</template>
</div>
As :key is not mandatory, It should work without that as well. I just created a working fiddle below. Please have a look and try to find out the root cause.
Vue.component('card', {
props: ['info'],
template: '<span>{{ info }}</span>',
});
var app = new Vue({
el: '#app',
data: {
sheets: [],
count: 0
},
methods: {
create() {
this.count++;
this.sheets.push('Sheet' + this.count);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="create">Create a Card!</button>
<template v-for="c in sheets">
<Card :info="c"></Card>
</template>
</div>

Using props how to update the data in Vuejs?

component
<template>
<div>
<b>Vuejs dynamic routing</b>
<div v-for="item in items" :key="item.id">
<b>{{ item.id }}.</b>
<router-link
#update="updateValue"
:to="{ name: 'UserWithID', params: { id: item.id, items: items } }"
>
{{ item.val }}{{ item.kk }}
</router-link>
</div>
<br /><br /><br />
{{ $route.params.id }}
</div>
</template>
Using props how to update the data in Vuejs?
I have two components called, helloworld, User. And i have mocked the data inside of helloworld.vue. Now using the props the want to get he data inside of the User component and preform the update operation . When trying to preform the logic.
Where onclick of button. it is going to method, But not updating the logic
I have kept console. inside method. and its printing. but logic not updating
As mentioned in the comments you are getting errors in the console as you are not passing the items as props to the User component and it is a required field in the User component.
And for the second point, you should store data in a separate file not in the main component so the items array doesn't get initialized again when the parent component is rendered again. The best option would be a global store(vuex) for sake of simplicity, it is done a separate file for now just as an example.
Here is a sample sandbox hope it helps:
https://codesandbox.io/s/exciting-ptolemy-35bsb?file=/src/components/User.vue

Vuejs - Passing parent component props to child element with the template

The problem I'm trying to solve is I want the child component to react when a v-expansion panel is expanded/contracted.
Normally this would be trivial, however, I'm attempting to pass a value from a prop within a vuetify component to component via a scoped slot. Because I'm rendering the child components within a loop, I can't just use Data to bind the prop.
<v-expansion-panel expand>
<v-expansion-panel-content
v-for="item in this.items"
:key="item.key">
<div slot="header">
content
</div>
<slot :items="item.children"></slot>
</v-expansion-panel-content>
</v-expansion-panel>
The v-expansion-panel-content has a prop called value. I need to bind that prop to the slot. Ideally, I'd like to achieve something like this:
<slot :items="item.children" :panelValue="value"></slot>
Any ideas would be greatly appreciated.
I've solved this, but in a less than ideal way.
<v-expansion-panel expand>
<v-expansion-panel-content
v-for="item in this.items"
:key="item.key"
v-model="item.isOpen">
<div slot="header">
content
</div>
<slot :items="item.children" :isVisible="item.isOpen"></slot>
</v-expansion-panel-content>

Components and Slots approach

I have actually 2 global components one for Admin and other one for Modal. The Admin component have a child comp called Page and the Page comp have others childs. I want to pass content directly to Page comp via slots. Like this:
app.js
new Vue({
el: '#app',
components: { Admin, Modal }
})
Admin.vue
<template>
<div>
<page>
<slot></slot>
</page>
</div>
</template>
export default {
components: { Page }
}
Page.vue
<template>
<div>
<page-header>
<slot name="page-header">
<h1 class="page-title">
<slot name="page-title">
Page Title
</slot>
</h1>
</slot>
</page-header>
<page-body>
<slot>
Page Body
</slot>
</page-body>
<page-footer>
<slot name="page-footer">
Page Footer
</slot>
</page-footer>
</div>
</template>
export default {
components: {
pageHeader,
pageBody,
pageFooter
}
}
index.html
<admin>
<div slot="page-header">
Header Test
</div>
Body Test
<div slot="page-footer">
Footer Test
</div>
</admin>
I don't need to use Page as global component, Please any idea?? Hope you understand what I'm looking for...
Thanks
I don't think slots are designed to do this. If you need data to be persisted between parent and children then use either props as #Belmin Bedak suggested. When you pass a prop to a component it will be available to all its children.
If you need to persist state on front-end I strongly recommend using Vuex as source of data for all components ( only use if it becomes more complex to have data scattered across components ).

Categories

Resources