Best way to use props passing to multiple children componets - vue.js

I have parent component that contains form component and detail component for created_at and updated_at in editing Product page.
Form is to edit the existing data and detail component will be next to the form.
I didn't have the detail component before so I fetch data from form component and use it in the component however I need some of the data in detail component which is the child of the parent of the form component.
So I moved the fetch axios to parent component and pass the data to both children now.
Is it better to do this way or is it better to send axios request both in form component and detail component?
The form is also used in adding new product.

My opinion is that you should fire requests from most top level possible. This way your children components (building blocks) can work independently from your current context. It's called presentational component and it's role is to output some markup. The container component feeds the data to the presentational component making the data flow go from top to the bottom nicely.
So in short, you did it right! However you should be careful, when your data changes in the edit form, then you probably want to fire the request on parent again, so that the data is updated for the whole app. This kind of flow is highly facilitated by Vuex. It serves as single source of truth (data) that your whole application can rely on.

Related

Maintaining view state when navigating to another view

I have one VuesJS view with two components in it that have a main-detail relationship. The user can click on an item in the main component (the item gets highlighted) and the details component will show the related detail items.
products.vue
<main></main>
<details>></details>
The user can edit a detail item and I want that to take place using a separate view containing the necessary components to edit the detail item.
I want the user to be able to navigate back to the products.vue view (say after finishing the editing process) with its state as it was when the initiated the editing operation.
I tried wrapping each of main and details in <keep-alive></keep-alive> but that did not seem to do the trick.
I have also read a few posts where <keep-alive></keep-alive> is used with the include property around the <router-view></router-view> but I'm not sure what to include in the include in my case.
Any thoughts on whether this is possible or what I'm doing wrong?
thanks
To persist state beyond route changes the state needs to either be stored:
in a component that is a parent to the <router-view> (such as <App>)
in a new vue instance with shared state that you import into the required components
in the official state management library Vuex (recommended)

If I have multiple components with input fields in vue router, how should I fetch data and store it in vuex?

In my vue cli project I have a route Settings with 3 child components SettingsA, SettingsB and SettingsC. Each child component has ca. 15 input fields, so it would be too many input fields for one single component.
The goal is to get data from a REST backend with an an axios call when the Route Settings is loaded, and populate some of the input fields with the data;
the user can then navigate between the child components and fill/change the input fields, without triggering the axios call which would reload and overwrite the users input field changes.
Since there are 3 child components I use vuex as store. That way the users inputs should not change when he navigates between the child components.
My question is: Where and with what hook should I make the axios call? With beforeMounted on the Settings Component?
Maybe there is also a better, already tried design than mine?
Thanks for your help!
Solution using custom events
You actually not necessarily need vuex. Basic idea is to have parent component Settings, which includes SettingsA, SettingsB and SettingsC, which are displayed conditionally using v-if. The Settings component is holding your state. Changes in the child components form fields trigger events with this.$emit(). The parent component listens to the events and updates its state. The state of the form is passed down via props.
Solution using Vuex actions
If you go the Vuex route, you will trigger actions instead of using this.$emit() and update the global store. You should import the actions using mapActions. In your components you then have access to the global store using this.$store.

Passing data to sub-components in Vue JS. Best practices?

I'm confused about best practices for passing data from parent to child components and modularity strategies.
As I know there are 2 ways:
Fetching data in parent component and send Array/object to the child via props
Send parent_id to the child via props and fetching data within the child component
Let's assume a use case working with a product edit view, having:
A parent component product
A child form component to edit basic product information
A child related_products component where other products can be linked/unlinked.
As per my experience, the first way works smoothly since it's all done in 1 request to the API: fetching a product object in parent component and passing through props the product itself to the form component and the nested objects to the related_products component. In addition, it can be done in beforeRouteEnter guard so the parent and all its children are shown with all the information at once. The cons I see here is that we have to send the correct object structure to the child component to avoid any error, having a strong dependency between components.
On the other hand, by sending the parent_id to every child component through props we release the parent from any logic. In this case, every child component acts as a "black box" and fetch/handles the information. The cons I see here is that we would have to perform 2 API requests for getting the product and the related products. In addition, the beforeRouteEnter is not viable at all, so we get an empty form/table until the data is retrieved.
This is not about how to code it, it's just about what's the best implementation as per your experience.
As far as my experience is concerned, 1-st way is better. Parent component acts as "smart" and you have access to it's life cycle hooks in order to trigger your api-requests, reset timers, e.t.c... I would also suggest to use vuex, as it allows you to make clean interface of communication between your parent component and "outer world", utilizing actions and getters.
With that being said, your "dumb" child component communicates with it's parent through props and emits interface. And because it is "dumb" - it's easier to test it or utilize something like "storybook".
we have to send the correct object structure to the child component to avoid any error
I guess, at the end of the day, you'll need correct object structure anyway, right? It could not be just random...

Two vue components calling same API function

I have two instances of a component on the same parent component and this child component makes an API call in the created lifecycle hook to populate a drop-down list. The list data will be the same for both instances of the child.
So the result is that when my parent component is loaded I'm actually calling the API twice which is unnecessary.
My question is if I want to just call the API once should I either move the API call to the parent and pass the drop-down list items to the child or use vuex and have the parent call an action that calls the API. The action would then save the items to state and the child component will access items via a store getter.
I'm tempted to use the vuex store as the list is small and might be needed elsewhere outside this current parent.
TLDR;
If you want to use it outside of the Parent-> child relationship use Vuex
If you know it will be simple and small, passing it down as a prop works just as well and reduces complexity of setting up the store.
Another option is to store it in localStorage, but this may be less reliable than you want as someone clearing their cache will lose functionality of the dropdown.
You can store it in a Vuex store allowing it to persist for anywhere in the application, however, if the parent is getting the list and it just needs to pass the list of dropdowns to the children, you could also just create a Prop in the children and pass the dropdown list that way.
The Children will have access to the dropdown items and you would not need to add the complexity of Vuex for a simple dropdown in a small app?
You mentioned the list not being very big, and if the dropdown is not something that the User is required to click every time or use, then having it as two API calls is not necessarily bad. You can just load the data when they attempt to access the dropdown at that point, which in some cases may save you and the customer the bandwidth of requesting a dropdown list when not needed.
You should go for Vuex store if you need to render same data to multiple components. Vuex store increases code complexity at initial setup level, but afterwords it is so simple and effortless to use API data in to the multiple components. It doesn't mean that use Vuex store in each application. If you are developing application that is progressive in nature and it will get more complex in future then start using Vuex store. It will help you in future developemnt. Here is all Vuex store details.

VUE.JS: Passing Data From Parent To Child Component

I have a layout file in which I have some data. Besides that I have three components:
tags
students
actions
I want to declare the data in the layout file, but access it through the three child-components.
How is this done in Vue.js?
Thank you for your help.
One option can be to pass the props to all the child components which is the norm in vue when it comes to passing data to child component, as also explained here.
Given that you want to pass same data to all these components and there can be cases going forward when you want to change this data and get it reflected in parent as well, you can go for a centralised state management, which is explained here in more detail.