Pass a value between two different vue components - vue.js

I am building an app using vue.js and I have a simple question. Im trying to transfer a value between two componenets which are not related to each other. What I actually do is that I have a chart and when I click on a point, I am assigning the points date to a var and trying to transfer it to the second component and give it to the datepicker. So the main question is that if it is possible to take a value ,which is different depending on the point clicked, and transfer it to the second vue component.
Thanks in advance!

Try passing the value as a prop: https://v3.vuejs.org/guide/component-props.html#passing-static-or-dynamic-props
If you need the prop to be reactive: https://v3.vuejs.org/guide/data-methods.html#data-properties
And please do not use var, use const (for variables that should not change reference) or let (for variables that may change references).

Related

Vue3 computed property in parent child component structure not working

After trying to find solution to this issue for hours on various forums i am posting this here.
So i have two components. 1) App and 2) Todo. Both renderes a list and i can complete items so there will be two lists one for incomplete items and one for complete items. you can click on item and it will be gone to complete items list.
So in my example you can see i am using same component but with two diffreent ways to give data to component. one using API and one using native js Data. in both cases it renderes but with api i can click on list item and it will be gone to completed list but with javascript array example it doesn't work. i am completely amazed with this because component is same. how it can affect like that.
many answer here do tell me that computed properties are not reactive as they are cached but what’s the solution to that ? i can put data variable but then the first case of api will not work because time it takes to fetch it. so please help me with this one.
complete code at sfc playground
You have reactivity issues the computed property probably expects that value to be constant because you provide a non-reactive array from the parent.
I think you have 2 options here:
you either provide a reactive prop from parent
or you set a local data attribute in the child-component so that vue will know that it can change
Your fiddle didn't work for me so I copied your code to codesandbox, I have both examples there but commented out the first solution, there you basically simply add the array to the data object and reference that in the code.
Second solution you can add a mounted hook to define reactiveAssignments to your data in the child component this way it will have the same reference so that's why it would work that way.
I think the first solution is simpler, but it is really up to which one you prefer.
You can check the solutions here in my codesanbox
A better approach could be though by setting up component events instead of v-models in the child you should use it in the parent because this way you are directly modifying the props. You can read more about this here: https://vuejs.org/guide/components/events.html#usage-with-v-model

How to update vue2-frappe chart?

I've been breaking my head over this for the last few hours and no matter where I look I can't seem to find the answer.
I'm using vue2-frappe as my chart library. I'm using a simple bar chart to display certain values by day. Everything was fine until my higher-ups decided they wanted to show a whole year's worth of values on this chart, meaning I have to add some pagination to it.
The problem is, now I can't figure out how to make the chart rerender. I've tried replacing the entire object I've bound the chart to, as well as manipulating specific values, but nothing seems to make the component rerender.
In the documentation for frappe.js, you can modify data via specific methods, but this being Vue I can't just call chart.update() like in normal .js. And if I inspect the component via vue dev tools, I can see it contains the modified data, it just doesn't redraw itself.
Anyone have an idea what to do?
I would try to force update the view component.
VueJs reactivity can sometimes be confusing where you think it should react to changes but it doesn't.
You can force a view update like so:
// Globally
import Vue from 'vue';
Vue.forceUpdate();
// Using the component instance
export default {
methods: {
methodThatForcesUpdate() {
// ...
this.$forceUpdate(); // Notice we have to use a $ here
// ...
}
}
}
You can read about correct ways of re-rendering here: https://michaelnthiessen.com/force-re-render
There are caveats to this approach as outlined in vueJs's docs: https://v2.vuejs.org/v2/guide/list.html#Caveats
Note #
A force re-render wont update computed values, but your computed property shouldn't contain any external non-reactive variable anyway.
Note 2
The above article written by Michael Thiessen also states the best way in his opinion is key-changing which I think we all should be aware of.
I hope this puts you on the right track. It sounds like (with limited information) you could be replacing the data but using the same key.

Pass entire data item vs just id as Prop in Vue list when using VueX

I have a VueX state that contains a list of items. E.g.:
{
operations: Operation[]
}
We need to display each Operation as an item in a list. So we have an OperationList component and an OperationItem component.
When it comes to rendering the list (v-for), would it be recommended to pass the entire item as a prop or just the id and have the OperationItem read the data from VueX?
Basically:
<operation-item v-for="operationId in operationIds" :id="operationId" :key="operationId"/>
vs
<operation-item v-for="operation in operations" :operation="operation" :key="operation.id"/>
I think it might be a preference choice but in my projects I usually pass all the prop of the components that way :
<operation-item
v-for="operation in operations"
:key="operation.id"
:prop1="operation.prop1"
:prop2="operation.prop2"
:prop3="operation.prop3"
/>
I'm not sure if that's a good practice or not but in this case, it's more flexible, you don't need to give a structured object for it to render, you just have to give it all it's properties.
A bit like for a class constructor, I would pass all the necessary parameters separately instead of passing them in an $option array or Settings class.
For some components, it also doesn't make sense for them to be aware of the store, they should juste be "stupid" rendered components.
I hope it's clear enough that you get my point !
I'd say pass the entire item. That way your component doesn't need to know where the data came from and you would be able to reuse the component in situations where the data didn't come from Vuex.

Editing information across separate Vue components

I've been learning Vue, and one thing that I'm struggling to understand is how can I edit information across two separate components.
I have a background in PHP, so setting a global variable would be one way to accomplish this in that. But with Vue, I'm not entirely sure.
For example:
Say that Component1 creates a text box that shows a value of "dog" somewhere on the page. And from Component1 you can update and change that value through input fields.
Later, say that Component5 also has an input field that needs to change that text box's value to "cat."
If these two components are separate, and Component1 is controlling that original value, then how can Component5 access that value, update it or manipulate it?
Essentially, what's the best way to handle a piece of information that needs to be accessed/changed from multiple different components or pieces of the Vue application?
Probably the best way will be to use Vuex. It provides a store, where you can add all data which you need in multiple components.
https://vuex.vuejs.org/en/intro.html

Vue.js 2.0 - creating reusable components

I am trying to create fully reusable component using Vue.js 2 and single file components, and right now my approach seems to be impossible to realize.
The goal is to create component for creating forms for a complex, nested JSON structure. This structure is supposed to be edited and then sent to the server. The component itself displays a header and submit button but the fields along with their placing is entirely the responsibility of the user of my component. (front-end engineer)
The MyForm component (implementation is not relevant here) is passed the JSON data and url to post them to.
The form is supposed to be reusable by many other users and the contents of the form itself is supposed to be not relevant. It may have a mix of html/inputs/custom components as children.
Let's imagine a simple scenario without data nesting with the following data:
var mymodel={ name : "My name", surname : "My surname" }
And a form i would like to create using my component:
<MyForm :model="mymodel" :url="http://localhost/post">
<div>
<MyTextInput v-model="model.name" label="Name"/>
<MyPanel>
<MyTextInput v-model="model.surname" label="Surname"/>
</MyPanel>
</div>
</MyForm>
Therefore:
MyForm gets passed a model to submit, stores it in data
MyTextInput is a custom component for displaying input with label
Second MyTextInput is the same component but created in another component contained called 'MyPanel' since this field needs to be placed differently.
As we can see there are many problems with passing variables and composition itself:
Composition:
If i put a <slot></slot> in the tempplate of MyForm for displaying the fields it would be compiled in parent scope, therefore all children (including MyTextField) would not have access to the "model"
If i try to use <MyForm inline-template> i cannot automatically display the form header and footer since all content is being replaced. Additionally when using single file components the compiler will look for all components inside the inline-template which means that i would have to import MyTextInput and MyPanel into MyForm which is not practical. I do not know in advance all components that will never end up in my form!
Passing variables:
If i use the variables directly from "model" (in first TextInput) i receive warning that i am modifying a variable from parent and it will be overwritten on next render (but in this case it will not be overwritten since i am INTENTIONALLY modifying the parent)
I cannot pass the model into second MyTextInput without passing it to MyPanel first. Actually i would have to pass it into EVERY custom component in between. And i do not know in advance how many custom components will there be. Which means that i would have to modify the code of every component that would ever be put into MyForm and require users to pass the data for each custom component they include.
If i would try to properly inform the parent about changes i would need to add v-on: event to every textinput and every custom component in between in order for the event to reach MyForm.
As i have said the component was supposed to be simple and easilly reusable. Requiring users of this component to modify code of every child they put into it and requiring them to add v-on: to every component inside does not seem practical.
Is my idea solvable using Vue.js 2.0 ? I have designed the same component before for AngularJS (1.5) and it was working fine and did not require to add modifications to each child of the form.
I've been using a ui framework based on vue 2.0 and you may get some ideas from its implementation. Based on its implementaion and my little experience with it, I think it's the person who uses your framework's responsibility to assemble the form-model. Also, for a form, we can always easily get all the data to be sent by using fields' value props without v-model's help.
The framework's doc on form element may also be helpful but it's currently only available in Chinese except for the code samples.
I suggest you to use Form Input Components using Custom Events to pass variables in your form.
Mutating a prop locally is now considered an anti-pattern, e.g.
declaring a prop a and then set this.a = someOtherValue in the
component. Due to the new rendering mechanism, whenever the parent
component re-renders, the child component's local changes will be
overwritten. In general, in 2.0 you should treat props as immutable.
Most use cases of mutating a prop can be replaced by either a data
property or a computed property.