I want to achieve this(Ref. attached image) in Angular 5
There Two components User-layout and role
User-Layout Component has been used at the start of Role component.
I am able to Expand and collapse the Parent component with animations but unable to to do the same simultaneously for the child component.
Any way to trigger animation on child component from the parent component.
For communication between child component and parent component you can use #Input, #Output and EventEmitter.
If you want to pass data from parent to child you can simply do it using #Input as below:
First you need to import Input into your child component using
import { Component, Input } from '#angular/core';
Then you need to declare an #Input variable in your child component
export class ChildComponent {
#Input() parentVariable: string;
}
Then while using the child component in you parent you need to specify the varible as an attribute as below
<child-component [parentVariable]="parentData"></child-component>
You should have a parentData declare in your parent component whose changes will reflect in the child component #Input variable parentVariable.
Thats all you need to do to and you need to animatation code which will trigger on the change of parentVariable variable.
Hope this helps!!!!
Take a look at animateChild() method.
Excerpt from the blog post posted by the #angular/animations author, Matias Niemelä, about animateChild()
Now what about the situation when there is an element in the application that has an animation ready-to-go, but a parent animation runs instead? Is there a way that the parent animation can dictate when the child animation runs, how long it runs for or if it doesn't run at all?
[...]
If these animations trigger at the same time then the parent animation will always win and the child animation will be skipped. However, using animateChild we can have the parent animation query into the child and tell it when it's allowed to animate:
Sub Animations With animateChild
component.html
<!-- do these two guys animate at the same time? -->
<div [#parent]="parentVal">
<div [#child]="childVal">
...
</div>
</div>
component.animations
trigger('parent', [
style({ transform: 'translate(-100px)' }),
animate('500ms',
style({ transform: 'translate(0px)' })),
query('# child', animateChild())
]),
trigger('child', [
style({ opacity:0 }),
animate('0.5s', style({ opacity:1 }))
])
Related
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.)
I would like to create a parent directive which shows or hides children based on the values of the children. To do this, i've taken the approach of a parent structural directive, and a child directive with values. For simplicity without the values:
<div *appParent>
<div appChild>1</div>
<div appChild>2</div>
<div appChild>3</div>
<div appChild>4</div>
</div>
To access the children, I use the following line in the parent directive:
#ContentChildren(AppChildDirective, { read: AppChildDirective, descendents: true }) children: QueryList<AppChildDirective>;
This query list is always empty. However, when I change it to a non-structural, it works fine. Stackblitz demo here
I assume this is due to the fact the structural directive creates a parent ng-template, which #ContentChildren then looks inside to find the original component, meaning that the query actually goes nowhere.
What approach can I take to access the children of the original component and not the template? Or do I need to take another approach to handle my requirements?
ContentChildren seem to not work on structural directives. However, this can be achived by injecting the parent directive in the child and then registering the child in the parent by calling a function.
#Directive({
selector: '[appChild]'
})
export class ChildDirective {
constructor(parent: ParentDirective) {
parent.registerChild(this);
}
}
#Directive({
selector: '[appParent]'
})
export class ParentDirective {
registerChild(child: ChildDirective) { /*...*/ }
}
Side notes
If you also want to be able to use the child directive without the parent directive, change the child's constructor like this to make the parent optional:
constructor(#Optional() parent: ParentDirective) {
parent?.registerChild(this);
}
You can also use this approach recursively by injecting a directive in its own constructor. If you do so, also add #SkipSelf() in the constructor to really get the parent:
#Directive({
selector: '[appRecursive]'
})
export class RecursiveDirective {
constructor(#Optional() #SkipSelf() parent: RecursiveDirective) {
parent?.registerChild(this);
}
registerChild(child: RecursiveDirective) { /*...*/ }
}
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
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 .
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'} />;
}
});