Accessing props in vue component data function
Asked Answered
S

6

103

I am passing a props to a component:

    <template>
       {{messageId}}
       // other html code
    </template>
    
    <script>
       export default {
          props: ['messageId'],
          data: function(){
             var theData={
                // below line gives ReferenceError messageId is not defined
                somevar: messageId,
                // other object attributes
             }
          }
       }
    </script>

In above code, I have commented the line that gives the error. If I remove that line, it works as normal and template renders properly (and I can see the expected value of {{messageId}} as well). Hence the logic to pass data is correct.

It seems that the way to access the messageId in data() is wrong. So how do I access the props messageId in data?

Scurrilous answered 10/3, 2017 at 15:49 Comment(2)
this.messageIdWaterhouse
Also, your data function needs to return the data object.Waterhouse
S
98

From the data() method, you can reference the component's properties using this.

So in your case:

data: function() {
  var theData = {
    somevar: this.messageId,
    // other object attributes
  }

  return theData;
}
Strunk answered 10/3, 2017 at 15:52 Comment(1)
data () { return { open: this.open, close: this.close } },Golanka
M
71

EDIT: According to Ryans posts it is possible to reference the instance with an arrow function like this:

data: (instance) => ({
  somevar: instance.messageId 
}),

PREVIOUS POST:

Note that this does not work if you are using an arrow function for assigning your data:

data: () => ({
  somevar: this.messageId // undefined
}),

Because this will not point to the component. Instead, use a plain function:

data: function() {
  return { somevar: this.messageId }
},

or using ES6 object method shorthand as Siva Tumma suggested:

data() {
    return { somevar: this.messageId }
}
Matrix answered 3/12, 2018 at 14:30 Comment(7)
Instead why not use data() {..}Knavery
I got burned by this once. It's a subtle difference but switching the function from arrow to data() {return {}} does the trick. Thanks mufasa.Antlia
Thanks a lot, was looking for it.Bounce
Thank you. This was very helpful.Journalize
You can use an arrow function actually— the first argument will be a reference to the instance. data: vm => ({ somevar: vm.messageId })Multivocal
I know I'm late to the party but this answer solved an issue I just ran into. My understanding (albeit probably wrong now obviously) was that all three function declarations are the same, just difference in syntactic sugar. I'll research this but if someone want to drop a hint I won't complain.Terrorstricken
@Terrorstricken Yes, the two bottom ones are the same and the top one is an arrow function which handles the context differentlyMatrix
M
16

To assign a data property equal to a props, you can use watcher, as following:

<script>
   export default {
      props: ['messageId'],
      data: function(){
         var theData={
            somevar: "",
            // other object attributes
         }
      },
      watch: {
        messageId: function(newVal) { 
           this.somevar = newVal
        }
      }
   }
Messaline answered 10/3, 2017 at 15:52 Comment(8)
Or use a computedSomehow
@RoyJ Yes, that also can be done, but If you want to update the data variable, than you have to use computed with getter.Messaline
I mean you should replace the data item with a computed, if somevar is never assigned by anything but the watcher.Somehow
@RoyJ Why is that needed?Messaline
It makes the code clearer. A computed is effectively a watcher plus a data item.Somehow
I will completely agree with you on that.Messaline
this will trigger an input event when you have an input v-model that dataRomilly
Thanks for this answer!Persuade
I
4

as @Saurabh described, I want to add more details.

If you are rendering a Child component, and want to set the data variables by props, you have to use both this and watch functions:

Step1. use this to access the props variables.

<script>
export default {

    data () {
      id: 0
    },
    
  
    props: ['propId'],
    methods: {
      init() { 
        this.id = this.propId  // step1. assign propId to id
      }
    }
}
</script>

Step2. watch the props variable

<script>
export default {

    data () {
      id: 0
    },
    props: ['propId'],
    methods: {
      init() { 
        this.id = this.propId  // step1. assign propId to id
      }
    },
    // add this to your code , this is a MUST. 
    // otherwise you won't SEE your data variable assigned by property
    watch { 
      propId: function(new_value) { 
        this.init()
      }
    }
}
</script>

Step3. understand the process of rendering Child component

Assuming you have two component: Parent and Child ( Child has a property naming as propId ) , and Child also have a "async" operation such as reading database.

// Parent's View

<Child propId='parent_var_id'></Child>

3.1 Parent got rendered

3.2 Child got rendered , in this case, parent_var_id blank

3.3 10ms later, parent_var_id changed to 100

3.4 Child property propId also changed as binding.

3.5 Child 's watch function called, and the variable id defined in data changed.

Impend answered 22/4, 2021 at 1:50 Comment(0)
S
0
<template>
   {{messaged}}
   // other HTML code
</template>

<script>
   export default {
      props: ['messaged'],
      data: function(){
         return () {
           some_var: this.messaged
         }
      },
      methods: {
      post_order: function () {
        console.log({
          some_var: this.some_var.id
        })
      }
    }

   }
</script>
Sonometer answered 27/9, 2018 at 8:12 Comment(3)
Please explain why your code is the correct answer.Oldster
because i tested itSonometer
Return won't have the brackets () after it. As you have did return () { some_var: this.messaged }Redmund
A
0

I think you have done your solution since the question posted a couple of month earlier. I faced the same problem yesterday, so tried out above solutions without no luck. However, I would like to share an alternative solution for this case that helps someone considerably. watch has some attributes to handle those type of cases. Below scrips shows that how do we accept the props value is data.

<script>
   export default {
      props: {
            messageId: {
                type: String,
                required: true
            }
        }
      data: function(){
         var theData= {
            somevar: "",
            // other object attributes
         }

         return theData;
      },
      watch: {
        messageId: {
                // Run as soon as the component loads
                immediate: true,
                handler() {
                    // Set the 'somevar' value as props
                    this.somevar = this.messageId;
                }
            }
      }
   }
</script>
Aleedis answered 14/1, 2020 at 5:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.