Passing objects to next sibling components - aurelia

My structure in AureliaJS of components is:
<parent>
<child1>
<child2>
</parent>
I have an object in child1 which I get with ajax requests:
export class Child1 {
fechedObject = {}:
}
I need this property with two-way binding and observable in the second component
export class Child2 {
// I need this fechedObject here
}
What is the best approach to get it?

I believe the best approach here is using two-way binding on both child models, to bind the model via two-way binding in the parent.
In your parent.html, you would need this:
<child1 fetched-object.two-way="fetchedObject"></child1>
<child2 fetched-object.two-way="fetchedObject"></child2>
And in both child view-models, you'd declare the variable as a bindable:
bindable()
public fechedObject;
This way any edits that happen in either children, will get passed on to the other child. If you want to prevent edits in child2 from affecting the object in child1, you can simply bind one-way using fechedObject.one-way or fechedObject.bind on your child2.

You can get a hold of <child1/> view model reference and bind it to <child2/>:
<child1 view-model.ref='child1'></child1>
<child2 data.bind='child1.fetchedObject'></child2>
So child.data just needs to be bindable:
export class Child2 {
#bindable
data
}

Related

How to find which parent component set input in children at Angular 14?

I got 2 different parent components, lets say Parent1 and Parent2.
Have a child named Child1 and this child component gets an input named Input1.
In this Input's setter function, how should I determine which parent set this input in template?
--Parent1 component template:
<Parent1>
<Child1 [Input1]="Inputvalue">
</Parent1>
--Parent2 component template:
<Parent2>
<Child1 [Input1]="Inputvalue">
</Parent2>
Input setter in Child1 component
#Input() public set Input1(value: string) {
// I want to know who just set this input. Parent1 or Parent2?
}
Here is a visualized explanation from another question on Stackoverflow:
I tried to set additional parent information in template but this is a big project and nearly 200 component is using this Child. Too much work to do.
Possible clear and easy methods appreciated.

Get v-if expression/data as plain text in child component

Hy there,
I try to create a custom Vue component which is shown based on v-if directive. I also want to change the directive data (modalStatus) value from inside the component.
<modal v-if="modalStatus"></modal>
To update the data from the component i use a method similar to this.
closeModal () {
this.$parent.modalStatus = false
}
The problem is that sometimes i don't know the name of the data model (modalStatus) , can be anything.
My question is how can i get the data/expression name as a plain text from the modal component ?
I'm planing to use something like this to update the modalStatus
this.$parent['anyName'] = false
Thanks and stay safe !
Later Edit. I know how to accomplish all of the above using props or v-model. I wonder if is possible using strictly v-if. Thanks!
There are several approaches to get to a method or property in the parent component from the child.
The 'Vue Way' is to emit a message telling the parent to close.
Send the name in as a property
Parent
<child modalName='modalStatus' />
Child
this.$parent[this.modalName]=false
Send in a method
Parent
<child :close='onClose' />
// component method
onClose(){
this.modalStatus=false
}
Child
this.close()
Emit a message
Parent
<child-component #close='modalStatus=false' />
// or call a method
<child-component #close='onClose' />
// component method
onClose(){
this.modalStatus=false
}
Child
this.$emit('close')

What is proper component composition and use of props in Vue.js?

I'm struggling with this concept in vue.js..
I'm assuming that a component in Vue is an entity with some (html) representation and internal data or state. The component can then change it's internal data based on user's interaction with the template and inform the 'outer world' about its internal changes via events.
But then to put the component in context of the application as a whole most components need to receive data from the 'outer world' which would be done via props. So for a component to be useful it most often needs to change not only it's internal state but also some data it was given from the outer context - but props cannot be mutated directly. The internal data is for the internal working of the component but the real purpose of a component is to transform the data in props.
Lets say we have a component which is, via props, given an object representing a user profile for instance. The role of the component is to let the user edit their profile.
- to avoid mutating the prop (or a subproperties of the prop), i'd add a local copy of the prop which the component could work with freely - but i'd also have to add a watch to update the local copy every time the prop gets updated by the parent via v-bind.
</template>
<input v-model="localUserProfile.name"/>
</template>
<script>
export default {
props: {
userProfile: {
type: Object,
required: true
}
},
data: function () {
return {
localUserProfile: this.userProfile
}
},
watch: {
userProfile (newVal) { this.localUserProfile = newVal }
}
}
</script>
I could replace the watch with a computed property based on the given prop and let the component work over the computed property but then where to assign the edited values? Use the computed property's setter and 'emit' on changes?
Both these cases seem like a lot of extra code for a very common and repetitive task. What are some other common approaches to this? Are any of my assumptions wrong?
You should not update the prop from the children component :
All props form a one-way-down binding between the child property and the parent one: when the parent property updates, it will flow down to the child, but not the other way around. This prevents child components from accidentally mutating the parent’s state, which can make your app’s data flow harder to understand.
In addition, every time the parent component is updated, all props in the child component will be refreshed with the latest value. This means you should not attempt to mutate a prop inside a child component. If you do, Vue will warn you in the console.
You can read more about it here
If you have no other solution than updating if from the children component, it might be worth thinking about a different data flow strategy or design. (Components Basics)

Emitting object or value in vue.js component child to parent communication

I would like to know which is better way to emit data to parent in vue component. From parent to child I pass prop object but from child to parent with $emit. Should I pass object or value? e.g.: { product } or product.id and also I have to reuse some data in the { product } like product.price on event listener. What should I use? Emit an object or just value then loop and condition in listener function?
Just use a two way sync here:
#product.sync="product"
In the child:
this.$emit('update:product', product)
Whenever you make a change to the property of the product.
This does not work in case of Pass by reference. I mean it works but Vue is screaming don't mutate props directly...
Where movie is an object and genres is an array. Child components props and event
props: {
genres: {
type: Array,
default () {
return []
}
}
}
...
this.$emit('changeGenreList', this.genres)
I had to make the local copy of this array with slice() and then I was emitting this copy.

How to define property types when passing props to grandchildren in Vue.js?

I have a Vue component foo inside my HTML and I pass a parameter to it like this:
<foo some="Some String"></foo>
Now inside the foo component I define the property type and default value like so:
export default {
name: "foo",
props: {
some: {
type: String,
default() { return '' }
}
}
}
The foo component's template has another component bar which I pass the some property: <bar :some="some"></bar>.
Now my question is: do I need to again define the type and default value for the some property, this time inside the bar component? So basically copy the props code from the foo component and paste it into the bar component or is there another way?
foo has ensured the type and default value, so there is no need to validate them in bar. If the type were something that has special behavior (e.g., boolean), you would need to specify it, but there's nothing special about string.
Every component instance has its own isolated scope. This means you cannot (and should not) directly reference parent data in a child component’s template. Data can be passed down to child components using props.
Passing data with props
What you need here is to use scoped slot:
Scoped slots allows you to pass props down from Parent components to Child components without coupling them together.