Access the parent's data on child events in Vue js - javascript

I have two components, one inside the other one. I have a click event on the parent component that should change the data value of the child component.
<template>
<div>
.....
.....
<my-component
:options="options">
</my-component>
</div>
.....
.....
</template>
<script>
...
...
data(){
}
methods:{
clickEvent(array_from_child){
this.array = array_from_child; //array is in my-component
}
}
components:{
....
}
</script>
I want to trigger the clickEvent method on child's element change. how to do that?

It seems like you're asking two different questions.
First, accessing a child's data from its parent:
If possible, you should pass the array to the child component using the child's props. Then simply change the array in the parent and any changes will be reflected in the child. If the array really needs to be in the child, then you can define a method to retrieve it.
<template>
<child-component ref="child">
</child-component>
</template>
methods: {
onClick() {
const myArray = this.$refs.child.getMyArray();
}
}
And then, in the child
methods: {
getMyArray() {
return this.myArray;
}
}
Second, triggering a change in the parent from the child
In this case, Flame's answer is most idiomatic. Emit a custom event in the child and listen for that event in the parent.

When you are going from a child to a parent, you should use events:
{
methods: {
clickEvent()
{
this.$emit('click', mydata);
}
}
So in your parent element, you can then attach your own callback to the emitted event like so:
<template>
<my-child-component #click="theParentMethod" />
</template>
You could also use some reactivity by passing an object reference from the parent to the child, so if you change the object in the child, the parent can detect the changes. However this comes with some reactivity gotcha's, see https://v2.vuejs.org/v2/guide/reactivity.html .

Related

this.$destroy vs v-if vue js with pages

i have a menu with many items. on item click I create a new Vue element (with Vuex store). The question is:
on close witch is outside the vue instance do I have to call this.$destroy or v-if="false" the root element.
<template>
<div v-if="closeVar">
....
</div>
</template>
<script>
export default {
...,
data() {
return {
closeVar: true
};
},
methods: {
onWindowsClose() {
this.$destroy() OR this.closeVar = false; ????
}
},
created() {
window[id + 'onWindowsClose'] = this.onWindowsClose;
}
}
</script>
From the $destroy docs:
In normal use cases you shouldn’t have to call this method yourself. Prefer controlling the lifecycle of child components in a data-driven fashion using v-if and v-for.
So the answer from the docs is that it's preferred to use v-if. Furthermore, you should place that v-if on the component's tag in the parent, not within the component on the root element:
Parent
<child v-if="closeVar"></child>
Otherwise, you'd only be removing the child's content rather than the entire component.
The difference there is, for example, the child's created hook would not be called again if you repopulated that particular instance with content (which would be possible because the component wouldn't have been destroyed.)

angular 2 variable returns null in child component method when called from parent component

I have parent and child component communication, I want to fire up a method in child component that should open up a modal and pass the data. When I call a function from parent using ViewChild, the variable in the child method component returns null, however should have data inside variable. When I fire same function within the child component, the data is available, but its not a case when called from parent component. What is missing and why I don't see data in child component, from fire up from the parent component?
parent.html
<button (click)="openModal()">New</button>
<child><child>
parent.ts
import { FilterComponent } from './../filter/filter.component';
#ViewChild(FilterComponent) filterComponent: FilterComponent;
openModal(){
this.filterComponent.openModal(); // when fired from here, the function in the child component fires, but the variable inside it returns null
}
child.html
<button (click)="openModal()">New</button>
<modal><modal>
child.ts
openModal(){
modalVisible = true;
console.log(this.filter) returns null; when fired from parent component
console.log(this.filter) returns "filter data"; when fired within the component
}
From what I can tell you are currently selecting ALL FilterComponents inside your parentComponent. In order to use this you need to be more specific. You can change your ViewChild to select only one FilterComponent if that fits your use case.
Example:
parent.html
<button (click)="openModal()">New</button>
<!-- notice the #child attribute -->
<child #child><child>
Then in parent.component.ts
import { FilterComponent } from './../filter/filter.component';
#ViewChild("child") filterComponent: FilterComponent;
openModal(){
this.filterComponent.openModal(); // now that you're only selecting one element this function call should have access to this values.
}
You can also reference the relevant stack blitz i made here: https://stackblitz.com/edit/angular-lqmc8x
Good luck!
I think you need an EventEmitter.
parent.html
<child (messageEvent)="openModal($event)"></child>
child.ts
import { Component, Output, EventEmitter } from #angular/core;
export class...
#Output() messageEvent = new EventEmitter<string>();
openModal(val) { this.messageEvent.emit(val); }
child.html
<button (click)="openModal(val)">Click</button>
or something like that.
I think you should rethink your architecture here.
If the method is triggered from the parent component only, then put into the parent component
If the the method is triggered from both parent AND child component, then put into a service

VueJS parent communication to child element

New to VueJS so hoping to get some advice on the best approach to take.
I have a parent containing multiple child components.
Once the child components have been created there is an event handler attached to each child
this.$parent.$on('save', this.save);
So that whenever I emit the following in the parent we call the child save method
this.$emit('save', block);
The problem that I'm seeing is that every child listen to events from this parent is reacting to this event.
Is there a better way to get a specific child to react to a parent click event?
Maybe you could try passing a prop with .sync modifier to a child, and then in the child component you should use computed property. This is an option but I don't know what are you trying to achieve, is there any specific reason that you must emit an event?
Read the vue.js dosumentation for props: https://v2.vuejs.org/v2/guide/components.html#Props
For what you are attempting, if possible, I'd use a Child Component ref and call a method on the child from the parent:
Vue.component('my-comp', {
template: "#my-comp-template",
props: ['name'],
methods: {
saveMyComp() {
console.log('Saved:', this.name);
}
}
})
new Vue({
el: '#app',
data: {
people: [{name: 'Bob'}, {name: 'Nelson'}, {name: 'Zed'}]
},
methods: {
saveChild(index) {
this.$refs.myComps[index].saveMyComp();
}
}
});
<script src="https://unpkg.com/vue#2.5.13/dist/vue.min.js"></script>
<div id="app">
<div v-for="(person, index) in people">
<button #click="saveChild(index)">saveMyComp</button>
<my-comp :name="person.name" ref="myComps"></my-comp>
</div>
</div>
<template id="my-comp-template">
<span> {{ name }} </span>
</template>
Remember the parent is already coupled to the child component -- since it knows it exists in the template declaration.

Get inner html of the component as a variable in vuejs 2

Say I have a vuejs component called child-component which is added to a parent component as follows.
<child-component>
<div>Hello</div>
</child-component>
N.B. this is not the template of the child component. This is how the child component is added to the parent.
How can I get the innerHTML, i.e. <div>Hello</div> in the child component as a string?
Inside the component, child-component, the HTML would be available in the mounted lifecycle handler as this.$el.innerHTML. The parsed vnodes would be available from this.$slots.default.
console.clear()
Vue.component("child-component",{
template: `<div><slot/></div>`,
mounted(){
console.log("HTML", this.$el.innerHTML)
}
})
new Vue({
el: "#app"
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js"></script>
<div id="app">
<child-component>
<div>Hello</div>
</child-component>
</div>
You could look at using Vue Child Component Refs. That will let you access the child component's innerHTML from the parent component.
Just add a ref attribute to your child component. It can be anything you choose:
<child-component ref="mychildcomponent">
<div>Hello</div>
</child-component>
Then in the parent methods, you can do something like:
let childEl = this.$refs.mychildcomponent
That will set childEl the entire child component that you've referenced. To get the innerHTML youd just have to go a little further, and do something like this:
let childEl = this.$refs.mychildcomponent.$el.innerHTML
That should give you a string of the child component's innerHTML.
This might help: https://v2.vuejs.org/v2/guide/components.html#Child-Component-Refs
Alternatively if you want to get it from the child component itself, just do the following within a method:
let componentHTML = this.$el.innerHTML
Hope that helps.

Change children class with parent onClick in React?

I have multiple parent components and within each parent component are nested children components. I'd like to have the class in the nested childrens' component change when a link in that parent component is clicked (a show/hide toggle type thing). I'm guessing this can be done by setting and changing state in the parent component on the click, but am not sure. Is this the correct way to handle this?
Is it usually best practice to hold state in the root component (I should note that the parent component explained above is not the root).
Any and all help is greatly appreciated. Thanks!
Generally, the higher up in your component hierarchy you can push state, the better. Then as the state changes in your parent/root component, new props will trickle down to child components. This makes your child components a lot simpler because they don't have to manage as much of their own state, if any.
In your case, you're exactly right. Handle the click event in your parent which will change your state, then render your child component with the correct className based on that state.
var Child = React.createClass({
render: function () {
return <div {...this.props}></div>;
}
});
var Parent = React.createClass({
handleLinkClick: function (e) {
this.setState({toggle: !this.state.toggle});
},
render: function () {
return <Child className={this.state.toggle ? 'yes' : 'no'} />;
}
});

Categories

Resources