I have this structure of my plugin index and service:
service.ts:
declare interface Params {
title: string;
description?: string;
type?: string;
duration?: number;
}
export default class ServiceToast {
public toastRef: any; // component
public constructor(modalRef: any) {
this.toastRef = modalRef;
console.log(this.toastRef);
}
public open(params: Params) {
this.toastRef.open(params);
}
}
Basically I have created a service that receives the component so that it interacts with the component as desired.
index.ts:
import _Vue from 'vue';
import Toast from '@/components/_includes/layouts/Toast.vue';
import ServiceToast from './service';
const ToastPlugin = {
install: (Vue: typeof _Vue, options?: any) => {
Vue.mixin({
created() {
Vue.prototype.$toast = new ServiceToast(Toast);
},
});
},
};
export default ToastPlugin;
Where I install the plugin and use the service that I showed previously.
Here I call the plugin and do the corresponding Vue.use but when I want to call it in any component:
<a @click="$toast.open({ title: 'Hola mundo' })">Hola, dame click!</a>
I get the following error: "TypeError: this.toastRef.open is not a function"
In the shims-vue-plugin.d.ts:
/* eslint-disable */
import Vue from 'vue';
import { AxiosInstance } from 'axios';
import 'webpack-env';
import { FieldFlagsBag } from 'vee-validate';
import { SnackbarProgrammatic as Snackbar, DialogProgrammatic as Dialog } from 'buefy';
import ServiceToast from './app-config/toast/service';
declare module 'vue/types/vue' {
interface Vue {
$auth: any;
$axios: AxiosInstance;
veeFields: FieldFlagsBag;
$dialog: typeof Dialog;
$snackbar: typeof Snackbar;
$toast: ServiceToast;
}
}
declare namespace NodeJS {
interface Process extends __WebpackModuleApi.NodeProcess {
server: boolean;
}
}
Does anyone know what it could be? or that I am missing since I can not find the error.
UPDATE: This is the Modal component:
<template>
<ModalComponent v-model="isActive" :close-inside="false" :is-footer="false"
ref="toast" @close="$emit('close')" :width="240" :min-width="240" class="toast">
<template slot="body">
<div class="toast-content has-text-centered">
<figure class="image is-128x128 flex-center" v-if="type === 'success'">
<img src="/static/img/images/success.png">
</figure>
<figure class="image is-128x128 flex-center" v-if="type === 'warning'">
<img src="/static/img/images/warning.png">
</figure>
<figure class="image is-128x128 flex-center" v-if="type === 'danger'">
<img src="/static/img/images/danger.png">
</figure>
<h1 class="is-size-3 has-text-weight-bold has-text-danger">{{ title }}</h1>
<p v-if="description">{{ description }}</p>
</div>
</template>
</ModalComponent>
</template>
<script lang="ts">
import {
Component, Prop, Vue, Watch,
} from 'vue-property-decorator';
import ModalComponent from '@/components/_includes/ModalComponent.vue';
@Component({ components: { ModalComponent } })
export default class Toast extends Vue {
public isActive: boolean = false;
public title: string = '';
public description?: string = '';
public type?: string = 'success';
public duration?: number = 1000;
open(params: any) {
this.isActive = true;
this.title = params.title;
this.description = params.description;
this.type = params.type ? params.type : this.type;
this.duration = params.duration ? params.duration : this.duration;
setTimeout(() => {
this.close();
}, this.duration);
}
close() {
this.isActive = false;
}
}
</script>
Well, the solution was simply to instantiate the component as a class and mount it so that it is anywhere in the project:
I hope it helps someone if they want to do something similar :)