Can we use props to pass variable in vue? - vue.js

Slall question:
I have a 2 parent components nesting the same child component inside of them.
I use props so the parents can tell the child what title to show.
this child component is a photo gallery. It makes a query to the database, download photos and show them up. classic.
I need the parents to tell the child where to get the photos from:
Get the photos from All users, for the home page
or
get only the photos from a specific user for a user's page.
I'm wondering if I can pass this information through a prop.
Is that possible? Can we use the info from a prop as a varialble inside of the setup() function?
Is there a better way to do this?

Passing objects from one component to a child component is the purpose of props.
You can pass many items through props. VueJS has the following types built-in:
String
Number
Boolean
Array
Object
Function
Promise
In the V3 VueJS guide it gives the following example of a prop being passed into a component and then being logged to the console inside the setup() method.
export default {
props: {
title: String
},
setup(props) {
console.log(props.title)
}
}
However, when using props, you should always mark whether the is required, what its type is and what the default is if it is not required.
For example:
export default {
props: {
title: String, // This is the type
required: false, // If the prop is required
default: () => 'defaultText' // Default needed if required false
},
setup(props) {
console.log(props.title)
}
}
It's important to note that when using default, the value must be returned from a function. You cannot pass a default value directly.

Related

VueJs - Set property in child component's $options based on prop

Reproducible example
https://codesandbox.io/s/youthful-banach-tc83p?file=/src/components/ChildComponent.vue
Background
In the project I'm working on, there are helper functions which depend on a translationFile property in the $options of the component. However, when the component is a generic one being implemented in different places, that property will be different depending on the implementation.
What I want to do
Is there a way that I can set a property in the child component's $options dynamically based on the parent component?
Helper function example
getLabel(labelKey) {
const { translationFile } = this.$options;
if (translationFile && labelKey) {
return this.$tc(`${translationFile}.labels.${labelKey}`);
}
},
this would be called from the child component (CC), hence this.$options would refer to the CC.
When the parent component (PC) is PC1.vue, the file it would look in would be tran1.js, when PC2.vue, then tran2.js
I was able to achieve what I wanted with.
props: {
translationFile: {
type: String,
required: true
}
}
mounted() {
this.$options.translationFile = this.translationFile
}
but any components which depended on this needed to be wrapped with <client-only></client-only>

Preferred way to access props in Vue Single File Component

Suppose I have a prop named message which I want to access from the script section of a .vue file.
I know that it can be accessed using this.$props.message and this.message from the data function.
Which is the preferred way to access props from different lifecycle hooks (created, mounted, etc), and from computed getters, and methods?
Component properties as well as passed in props should always be referenced to by this.propName, because you shouldn't assign a component property with the same name as a passed in prop. In this case Vue will respond with an error.
As Aer0 said, they shouldn't have the same names:
props: ['propMessage'],
data() {
return {
message: ''
};
},
created() {
console.log(this.propMessage);
console.log(this.message);
}

Tracking a child state change in Vue.js

I have a component whose purpose is to display a list of items and let the user select one or more of the items.
This component is populated from a backend API and fed by a parent component with props.
However, since the data passed from the prop doesn't have the format I want, I need to transform it and provide a viewmodel with a computed property.
I'm able to render the list and handle selections by using v-on:click, but when I set selected=true the list is not updated to reflect the change in state of the child.
I assume this is because children property changes are not tracked by Vue.js and I probably need to use a watcher or something, but this doesn't seem right. It seems too cumbersome for a trivial operation so I must assume I'm missing something.
Here's the full repro: https://codesandbox.io/s/1q17yo446q
By clicking on Plan 1 or Plan 2 you will see it being selected in the console, but it won't reflect in the rendered list.
Any suggestions?
In your example, vm is a computed property.
If you want it to be reactive, you you have to declare it upfront, empty.
Read more here: reactivity in depth.
Here's your example working.
Alternatively, if your member is coming from parent component, through propsData (i.e.: :member="member"), you want to move the mapper from beforeMount in a watch on member. For example:
propsData: {
member: {
type: Object,
default: null
}
},
data: () => ({ vm: {}}),
watch: {
member: {
handler(m) {
if (!m) { this.vm = {}; } else {
this.vm = {
memberName: m.name,
subscriptions: m.subscriptions.map(s => ({ ...s }))
};
}
},
immediate: true
}
}

Creating local copy of passed props in child component in vue.js?

In vue.js what is the right way to edit prop without changing parent data?
What I mean by that is whenever we pass any property from parent to child in vue.js then if we make any change to that property in child component then the change is also reflected in parent's component.
Is there any way in vue.js to make a local copy of passed property in a child?
I googled this but everywhere it is written that we can achieve this by doing this.
props:["user"],
data(){
return {
localUser: Object.assign({}, this.user)
}
}
here the user is passed an object and I am creating a copy of it in local user but it doesn't work at all, the local user is undefined.
Have you encountered a scenario like this where you have to make changes to a parent property in child component without affecting the state of parent component i.e- making your own copy in child and then edit it?
Any insights on this will be helpful.
I have also read somewhere that in In vue#2.3.3,when we want to pass a prop from Father to Child component, we need to manually create a local data to save the prop, that makes lots of useless works.
we can maually create the local data like this :
props: ['initialCounter'],
data: function () {
return { counter: this.initialCounter }
}
but this is not working in my case as well.
I am using vue cli 3.0.1 for the developemnt purpose.
Here is my code for the same.
In my application I have a list view.
When user clicks on the See Focused View button user is redirected to below mentioned view i.e is actaully a bootstrap - modal view.
Here user can edit the value of Name, but as I am passing name here as a property from aprent component so editing it here causes it to update on parent component as well i.e in the list view as well.
In your fiddle, the child component is using Object.assign() to create a copy of data, which is an array of objects. However, this only creates a shallow copy, so the array elements would still refer to the original instances, leading to the behavior you're seeing.
A few solutions to deep copy the array:
Use JSON.parse(JSON.stringify(this.data)), which works reasonably well for primitive object properties (String, Number, BigInt, Boolean, undefined, and null):
data() {
return {
local_data: JSON.parse(JSON.stringify(this.data))
}
}
(demo 1)
Map the objects into new ones, which works well if the depth is only 1 (nested arrays/objects will still be shallow copied):
data() {
return {
local_data: this.data.map(x => ({...x}))
}
}
(demo 2)
Use a utility library, such as lodash's cloneDeep:
data() {
return {
local_data: _.cloneDeep(this.data)
}
}
(demo 3)

Passing data to Vue.js component

I am creating a component and want to pass two properties (item & brokerageID) to the component. Here is the HTML code:
{{brokerageID}}
<holiday-component v-bind:item="item" v-bind:brokerageID="brokerageID" testID="45" ></holiday-component>
Here is the code for 'holiday-component'
Vue.component('holiday-component', {
props: ['item',
'brokerageID',
'testID',
],
data () {
return {
holidaysData: [],
showHolidays: false,
}
},
methods: {
getHolidays(contactID) {
....
},
template: <div> {{testID}} {{item.contactName}} {{brokerageID}}
....
The 'item' property is getting passed to the component (item.contactName is displayed correctly in the component template. However, somehow, brokerageID (property of the Vue object) is not getting passed. This property exists which is confirmed as {{brokerageID}} used above the component in HTML displays value. But, within the component template, brokerageID is not available. Also, the testID property passed to the component is not displayed.
Could someone please advise, what is wrong in my implementation that I am unable to use brokerageID in my component?
See Vue's docs about prop naming https://v2.vuejs.org/v2/guide/components.html#camelCase-vs-kebab-case
In this instance, using v-bind:brokerage-id and v-bind:test-id should do the trick.