Update props value in child component in vue - javascript

parent.vue
<template>
...
<div>{{ meet}} </div>
...
</template>
...
props: ["meet"]
child.vue
<template>
...
<meet :meet="showMeet(e.id)" />
</template>
...
props: ['meet'],
...
methods: {
showMeet(id) {
this.meet == 'abc';
}
}
How do i update the value of the props to be used in child component

You may need to re-render the child component again. As per my understanding so far, the same prop is present in both the child's and if you update it's value from one, then you want to update it in second too. Refer this
https://michaelnthiessen.com/force-re-render/

Related

Vue: Get method from component that is in scoped slot

Component Page:
...
<Child>
<template #form="{ init }">
<PageForm :init="init"/>
...
Component PageForm:
...
methods: {
getData() {
// i need to call in component-grandchild of Page-component
}
}
...
Component Child (render-function):
...
h('GrandChild', {scopedSlots: {form = props => h('div', this.$scopedSlots.form(props)}}
...
Component GrandChild:
template:
...
<div>
<slot name="form" :init="init">
<div>
...
script:
...
mounted: {
// how here get method getData from Page->PageForm without Vuex?
}
...
I understand that if the structure of the components is constant, then you can try this.$parent.$parent. But this way you can get to the Page, but inside the PageForm is problematic, because this is the slot area.
In theory, i can hang a ref on a component, and get a method through it, but the behavior there is unpredictable...
It is most correct to exchange data through props/emit if the components are adjacent.

how to pass components as props in vue js and how to use it properly?

Hello I have a Child component that the main function is to filter and render a list of items. This child component is to be used in multiple parent components(views) and depending on the parent component the child component need to render a different child component (grand child).
Parent Component
<template>
<main>
//Child Component
<list-component
name="my items"
//List of Items I need to render
:list="items.list"
>
//Slot Passing my grandchild component
<template slot="child-component">
<component :is="child_component" :items="item"></component>
</template>
</list-component>
</main>
</template>
<script>
import ListComponent from '.ListComponent';
import ItemComponent from '.ItemComponent.vue';
export default {
components: {
ListComponent,
ItemComponent
},
data() {
return {
child_component: 'ItemComponent'
};
},
}
</script>
ListComponent.vue (child component)
<template>
<main>
<v-row class="ma-0">
<v-col v-for="(item, index) in list" :key="index" class="pa-0">
// I would like render my grandchild component here.
<slot name="child-component"></slot>
</v-col>
</v-row>
</main>
</template>
<script>
export default {
props: {
name: {
type: String,
required: true
},
list: {
type: Array,
required: true
}
}
};
</script>
ItemComponent.vue (grand child)
<template>
<div>
<v-img
src="item.image"
></v-img>
<v-row>
<span>{{
item.name
}}</span>
</v-row>
</div>
</template>
<script>
export default {
props: {
item: {
type: Object,
required: true
}
}
}
</script>
So basically I need to be able to pass ItemComponent.vue(grandchild) from the View(grandfather) to the View's ListComponent.vue(child) so that the child component can loop trough the items passed from the parent and use the grand child to render the information.
Also where do I declare the props for the grandchild?
I was able to find a solution after all I will leave this for those who need it.
basically in the child component we need to give access to the attribute to the parent trough the slot by binding the item like:
<slot name="child-component" :item="item"></slot>
and on the parent we can access it by binding the slot and giving a name to the object in this case I chose child and notice that on the component we can access item by declaring child.item
<template v-slot:child-component="child">
<component :is="child_component" :itinerary="child.item"></component>
</template>

How to pass data from child to parent component in vue?

I am using Vue.Js where i am calling my child component multiple times from parent. Which means there are separate instance created for all the different call. Data "json" will contain seperate value for all the different instance.
Now i want to fetch data present in variable json in all the instance of child component from parent component.
[Code]
Parent component
<div v-for="(value, index) in inputs" :key="index++">
<ChildComponent :componentcount="index" ></ChildComponent>
</div>
Child Component
<template>
<div id="hello">
<div>
<v-text-field :id="'ComponentHeader_' + $attrs.componentcount" v-model="header"
class="headertag" label="Child Tag" #change="createJson" outlined>
</v-text-field>
</div>
</div>
</template>
<script>
export default {
data(){
return{
json:"",
}
}
}
You can use $emit method for this purpose.
v-on directive captures the child components events that is emitted by $emit
Child component triggers clicked event:
export default {
methods: {
onClickButton (event) {
this.$emit('clicked', 'someValue')
}
}
}
Parent component receive clicked event:
<div>
<child #clicked="onClickChild"></child>
</div>
export default {
methods: {
onClickChild (value) {
console.log(value) // someValue
}
}
}

Passing props into template

How do I pass props into a component in the markdown/template syntax?
Can I do something like React <component :props="myObject">? and how would I handle that inside my component? Do props have to be declared inside my component also or can I have "unknown" set of props?
My instinct, React influenced, would do:
<template>
<div>
<component :is="Form" :prop="{title: 'foo', subTitle: 'bar'}"></component>
</div>
</template>
and in my Form.vue file I would have not have to declare props, and would declare data like:
data(){
return {title: '', subTitle: ''};
}
As per the documentation:
A prop is a custom attribute for passing information from parent components. A child component needs to explicitly declare the props it expects to receive using the props option:
In your case, parent component:
<template>
<child :title-data="sample_data"></child>
</template>
You can set the data in 'sample_data' in parent component.
data: function () {
return {
sample_data: {
'title': '',
'subtitle': ''
}
}
}
Child component:
<template>
<span> {{ titleData.title }} </span>
<span> {{ titleData.subtitle }} </span>
</template>
<script>
export default {
name: 'child',
props: ['titleData']
}
</script>
Yes, you have to declare the props inside the component. You can declare it in the above way or you can be more explicit about the props thus validating the props. Read this on how to go about it: https://v2.vuejs.org/v2/guide/components.html#Prop-Validation
Also read about kebab-case vs camelCase in props: https://v2.vuejs.org/v2/guide/components.html#camelCase-vs-kebab-case
Read more about props: https://v2.vuejs.org/v2/guide/components.html#Props

Is it possible to pass a component as props and use it in a child Component in Vue?

In a Vue 2.0 app, let's say we have components A, B and C.
A declares, registers and uses B
Is it possible to pass C from A to B?
Something like this:
<template>
<div class="A">
<B :child_component="C" />
</div>
</template>
And use C in B somehow.
<template>
<div class="B">
<C>Something else</C>
</div>
</template>
The motivation: I want to create a generic component B that is used in A but receives from A its child C. Actually A will use B several times passing different 'C's to it.
If this approach is not correct, what is the proper way of doing it in Vue?
Answering #Saurabh
Instead of passing as props, I tried the suggestion inside B.
<!-- this is where I Call the dynamic component in B -->
<component :is="child_component"></component>
//this is what I did in B js
components: {
equip: Equipment
},
data () {
return {
child_component: 'equip',
_list: []
}
}
Basically I'm trying to render Equipment, but the dynamic way
I get 3 errors in console and a blank page
[Vue warn]: Error when rendering component at /home/victor/projetos/tokaai/public/src/components/EquipmentFormItem.vue:
Uncaught TypeError: Cannot read property 'name' of undefined
TypeError: Cannot read property 'setAttribute' of undefined
Apparently I'm doing something wrong
Summing up:
<!-- Component A -->
<template>
<div class="A">
<B>
<component :is="child_component"></component>
</B>
</div>
</template>
<script>
import B from './B.vue';
import Equipment from './Equipment.vue';
export default {
name: 'A',
components: { B, Equipment },
data() {
return { child_component: 'equipment' };
}
};
</script>
<!-- Component B -->
<template>
<div class="B">
<h1>Some content</h1>
<slot></slot> <!-- Component C will appear here -->
</div>
</template>
You can use special attribute is for doing this kind of thing. Example of dynamic component and its usage can be found here.
You can use the same mount point and dynamically switch between multiple components using the reserved element and dynamically bind to its is attribute.
Here's how is can be used with either an imported component or one passed as a prop:
<template>
<div class="B">
<component :is="myImportedComponent">Something</component>
--- or ---
<component :is="myPassedComponent">Something else</component>
</div>
</template>
<script>
import myImportedComponent from "#/components/SomeComponent.vue"
export default {
props: {
myPassedComponent: Object
},
components: {
myImportedComponent
},
}
</script>
Here's solution to forward custom component through props of another component
:is is special attribute and it will be used to replace your actual component and it will be ignored if you try to use it as a prop in your component. Luckily you can use something else like el and then forward this to component like so:
<template>
<div>
<component :is="el">
<slot />
</component>
</div>
</template>
<script>
export default {
name: 'RenderDynamicChild',
props: {
el: {
type: [String, Object],
default: 'div',
},
},
}
</script>
Any valid element you use in el attribute will be used as a child component. It can be html or reference to your custom component or div by default as specified in component declaration.
Passing custom component to prop is little bit tricky. One would assume you declare in a components property of parent component and then use it for el attribute but this doesn't work. Instead you need to have your dynamic component in data or computed property so you can use it in a template as a prop. Also note AnotherComponent doesn't need to be declared in components property.
<template>
<RenderDynamicChild :el="DynamicComponent">
Hello Vue!
</RenderDynamicChild>
</template>
<script>
import RenderDynamicChild from './DynamicChild';
import AnotherComponent from './AnotherComponent';
export default {
name: "ParentComponent",
components: { DynamicChild },
data() {
return {
DynamicComponent: AnotherComponent,
};
},
};
</script>
Using computed property for your dynamic component allows you to switch between components easily:
<script>
import DynamicChild from './DynamicChild';
import AnotherComponent from './AnotherComponent';
export default {
name: "ParentComponent",
components: { DynamicChild },
data() { return { count: 0 } },
computed: {
DynamicComponent() {
return this.count % 2 > 1 ? AnotherComponent : 'article';
},
},
};
</script>
Increase this.count to alternate between AnotherComponent and simple article html element.
Maybe it's too late to answer this question. But I think it could help others with this same issue.
I've been looking for a way to pass components throw others in vue, but it looks that VUE3 have a approach for that using named slots:
Here it's the documentation about that:
https://v3.vuejs.org/guide/component-slots.html#named-slots
Basically you can have:
<template>
<div class="A">
<slot name="ComponentC"></slot> <!-- Here will be rendered your ComponentC -->
</div>
<div class="A">
<slot name="ComponentD"></slot> <!-- Here will be rendered your ComponentD -->
</div>
<div class="A">
<slot></slot> <!-- This is going to be children components -->
</div>
</template>
And from your B component
<template>
<div class="B">
<A>
<template v-slot:ComponentC>
<h1>Title of ComponentC </h1>
</template>
<template v-slot:ComponentD>
<h1>Title of ComponentD </h1>
</template>
<template v-slot:default>
<h1>Title of child component </h1>
</template>
</A>
</div>
</template>
If you would like to use another component within your functional component you can do the following:
<script>
import Vue from 'vue'
import childComponent from './childComponent'
Vue.component('child-component')
export default {}
</script>
<template functional>
<div>
<child-component/>
</div>
</template>
Reference:
https://github.com/vuejs/vue/issues/7492#issue-290242300
If you mean Dynamically importing a component in a parent component, so yes, you can do that in Vue3 using:
<component :is="child_component" />
but to render "child_component" itself dynamically, you can use
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() =>
import('./components/MyComponent.vue')
)
Let me give you an example:
let's say you have several multiple child components (ChildA, ChildB, ChildC) that you want to load dynamically based on what you pass to the parent component (Parent), so the Parent component will be something like this:
Parent
<script setup lang="ts">
import { defineAsyncComponent } from 'vue';
const props = defineProps<{
childComponent?: string;
}>();
const AsyncComp = defineAsyncComponent(() =>
import(`./${props.childComponent}.vue`)
)
</script>
<template>
<component :is="AsyncComp"/>
</template>
and then you can call the Parent component dynamically wherever you want like this:
<Parent :childComponent="child-a"/>
<Parent :childComponent="child-b"/>
<Parent :childComponent="child-c"/>
For a better explanation, you can check this article:
https://medium.com/#pratikpatel_60309/dynamic-importing-component-templates-with-vue-js-78d2167db1e7

Categories

Resources