1

I'm building a controlled component (one component is a parent and the other one is a child). Parent component is SurveyContainer and child is SurveyPage1. In SurveyContainer I have a model object surveyModel and nested object surveyModel.topPreferencesObj which I want to be initialized in SurveyPage1. So I'm passing this object as a prop.

 <template>
<div>  
    <SurveyPage1
            v-bind:prefObj="this.surveyModel.topPreferencesObj" 
            @handle-change="this.handleChange(arg)" >   

    </SurveyPage1> 
</div>

@Component({
components: {
    SurveyPage1
}
})
export default class SurveyContainer extends Vue {

mounted(){ 

}
surveyModel = { 
    topPreferencesObj : {
        option1: false,
        option2: false,
        option3: false,
        option4: false,
        other:""
    }
} 
handleChange(payload:any) {   // this never fires 
    this.surveyModel.topPreferencesObj = payload;  
}
}

This is SurveyPage1. Here I receive property object. Also here I have a watch which triggers everytime when something changes. So when it triggers I want to emit so that parent component knows that property was updated. But inside watch function i'm getting TypeError: Cannot read property 'handle-change' of undefined I am new to vuejs and I'm really in a hurry now. I search the Internet and it looks like it should work but it doesn't.

<template>
<div>
    <h2>Survey Page 1</h2>
    <v-checkbox v-model="prefObj.option1" label="" >
    </v-checkbox>
</div>
</template> 
<script lang="ts">
 import { Component, Vue,Prop ,Watch} from 'vue-property-decorator'; 
 @Component
 export default class SurveyPage1 extends Vue {

    @Prop({required: true})
    prefObj:any;

    computed(){
        debugger;
        const blah =  this.prefObj;
    }

    @Watch('prefObj', { immediate: true, deep: true })
    onPrefObjChanged = (val: any, oldVal: any) => {
        debugger;

        this.$emit('handle-change', this.prefObj);  // here I get the error: handle-change undefined
    } 
  } 
 </script>

Thanks.

Taras Kryvko
  • 177
  • 1
  • 9
  • Remove the `this.` parts in your template. Template expressions are already evaluated in the context of your component instance. `arg` is also not defined, just use `@handle-change="handleChange"`. Also, you should use kebab-case for your prop attribute names, ie `v-bind:pref-obj="surveyModel.topPreferencesObj"`. See https://vuejs.org/v2/guide/components-props.html#Prop-Casing-camelCase-vs-kebab-case – Phil Mar 31 '20 at 06:28
  • can you do `@handle-change="handleChange($event)"` (without `this`) and change case `this.$emit('handleChange', this.prefObj)` – Syed Mar 31 '20 at 06:28
  • Removed 'this' ,changed to kebab-case. Still getting the error. – Taras Kryvko Mar 31 '20 at 06:52
  • Ok, I found out that it doesn't work only inside @Watch handler – Taras Kryvko Mar 31 '20 at 10:45

1 Answers1

1

Ok, so the problem was that I used incorrect @Watch handler incorrectly

I had:

@Watch('prefObj', { immediate: true, deep: true })
onPrefObjChanged = (val: any, oldVal: any) => { 
    this.$emit('handle-change', this.prefObj); 
} 

where it should be

    @Watch('prefObj', { immediate: true, deep: true })
    onPrefObjChanged (val: any, oldVal: any) { 
        this.$emit('handle-change', this.prefObj); 
    } 

Conclusion : simple function instead of arrow function

kaiser
  • 21,817
  • 17
  • 90
  • 110
Taras Kryvko
  • 177
  • 1
  • 9