javascripttypescriptvue.jsjavascript-decorators

How I can make @Model and @Emit work together in VueJs with Typescript?


can anyone help me with decorators @Model and @Emit? I'm trying to change order on click in my component and used documentation from here: https://github.com/kaorun343/vue-property-decorator. Here is my code:

<template>
<button @click="onSortClick">Sort</button>
</template>  

<script lang="ts">
import Vue from "vue"; 
import { Emit, Componet, Model } from "vue-property-decorator";

export default class MyButton extends Vue {

    @Model("sort", { type: String, default: "none" }) readonly order!: string;

    @Emit("sort")
    onSortClick() {
        const nextSortOrder = {
                ascending: "descending",
                descending: "none",
                none: "ascending"
        };
        return nextSortOrder[this.order];
    }
}
</script>

But when I click the button, the value of variable "order" is not changing. Am I doing something wrong?


Solution

  • Yes, you are. There are a few things wrong here.

    1. You need to import vue like this import { Vue, Component, Model, Emit } from 'vue-property-decorator;

    2. The class needs to have an @Component decorator like this

    @Component({/* Additional data can go in here */})
    export default class MyButton extends Vue {}
    
    1. This isn't how vue intended emitting of events to work. You cannot alter the value of order because it is a readonly property within the same file. If you place your button in another component like this
    // ParentFile.vue
    
    <template>
        <my-button @sort="order = $event"></my-button>
    </template>
    
    <script lang="ts">
      import { Component, Vue, Watch } from 'vue-property-decorator';
      import MyButton from '@/components/MyButton.vue';
    
      @Component({
        components: {
          MyButton
        }
      })
      export default class Home extends Vue {
        order = 'Wow';
    
        @Watch('order')
        orderChanged(newVal: string) {
          // eslint-disable-next-line no-console
          console.log(newVal); // order will change here
        }
      }
    </script>
    

    and listen to the emitted event as above then the order variable in the parent component will change but not the child.