I tried to pops out sweetalert if failed to retreive data from server
I've imported sweet alert in main.js :
import VueSweetalert2 from 'vue-sweetalert2'
import 'sweetalert2/dist/sweetalert2.min.css'
const app = createApp(App)
app.use(VueSweetalert2)
app.mount('#app')
And inside the Table.vue components i tried to call swal but got an error says (undefined $this.swal) instead :
<script>
import axios from 'axios'
import { onMounted, ref } from 'vue'
export default {
setup() {
let transactions = ref([])
onMounted(() => {
getTransactions()
})
async function getTransactions() {
try {
let { data } = await axios.get('http://127.0.0.1:8000/api/transactions')
transactions.value = data.data
} catch(e) {
this.$swal('Something went wrong.')
}
}
return {
transactions
}
}
}
</script>
Any suggestion how to solve this ?
You can't use this as the component instance inside setup() because the component has not been created yet. There are other ways to get that $swal property.
vue-sweetalert2 exposes SweetAlert via app.config.globalProperties.$swal or as a provide-ed $swal prop.
A simple way to use it in the Composition API is through inject():
import { inject } from 'vue'
export default {
setup() {
const swal = inject('$swal')
async function getTransactions() {
//...
swal('Something went wrong.')
}
}
}
demo 1
However, the vue-sweetalert2 docs recommend using sweetalert2 directly in this case:
When using "Vue3: Composition API" it is better not to use this wrapper. It is more practical to call sweetalert2 directly.
You can use sweetalert2 directly like this:
import { onMounted, inject } from 'vue'
import Swal from 'sweetalert2'
export default {
name: 'App',
setup() {
async function getTransactions() {
//...
Swal.fire('Something went wrong.')
}
onMounted(() => getTransactions())
}
}
demo 2
In main.js file
import VueSweetalert2 from 'vue-sweetalert2';
import 'sweetalert2/dist/sweetalert2.min.css';
const app = createApp(App);
app.use(VueSweetalert2);
window.Swal = app.config.globalProperties.$swal;
app.mount("#app");
Use Swal.fire() inside COMPOSITION API
export default {
setup() {
function yourFunctionName() {
Swal.fire('Hello !')
}
}
}
Related
I want to format my date-time outside the component.
function transformDatetime(config, value) {
if (value) {
return $d(new Date(value), config);
}
return $t('-');
}
I'm trying to get $t from the App instance. But it only works in the context of the component, just like useI18n.
import { getCurrentInstance } from 'vue'
export default function useGlobal() {
const instance = getCurrentInstance()
if (!instance) return
return instance.appContext.config.globalProperties
}
I found a solution. Just import your i18n into a file outside the application and use i18n.global.t
import { createI18n } from "vue-i18n"
export const i18n = createI18n({
legacy: false,
locale: 'ja',
fallbackLocale: 'en',
messages,
})
import { i18n } from '#/i18n'
const { t: $t, d: $d, n: $n } = i18n.global
const expample = $t('some-text')
I think your method should also be a composable so you can simply use the method useI18n() inside.
Something like
use-transform-datetime.ts
import { useI18n } from 'vue-i18n'
export const useTransformDatetime = () => {
const { t } = useI18n()
const transformDatetime = (config, value) => {
if (value) {
return $d(new Date(value), config)
}
return t('-')
}
return {
transformDatetime
}
}
then simply use it in your vue file who need it
<script setup>
import { useTransformDatetime } from 'path-to-your-composables/use-transform-datetime'
const { transformDatetime } = useTransformDatetime()
console.log(transformDatetime(config, 'value'))
</script>
This way you can even add your others transform methods in the same composable
Try to use of the useI18n composable function from vue-i18n to get the t method instead of $t:
<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
console.log(t('greeting'))
</script>
Is there a way to get access to $vuetify (and any other added global) in the setup function?
Is there a way for composables to access it?
...
setup() {
const { isDesktop } = $vuetify.breakpoints.mdAndUp; // <=== how to get $vuetify
return { isDesktop };
},
Composable to get vuetify instance:
// useVuetify.ts
import { getCurrentInstance } from 'vue'
export function useVuetify() {
const instance = getCurrentInstance()
if (!instance) {
throw new Error(`useVuetify should be called in setup().`)
}
return instance.proxy.$vuetify
}
Import it in your component:
<!-- MyComponent.vue -->
<script lang="ts">
import { useVuetify } from './useVuetify'
import { computed } from 'vue'
/*...*/
setup() {
const vuetify = useVuetify()
const isDesktop = computed(()=>vuetify.breakpoints.mdAndUp)
return { isDesktop }
},
/*...*/
</script>
If you are using Vue <= 2.6.14 + #vue/composition-api instead of Vue 2.7, replace 'vue' with '#vue/composition-api'
As #Lagamura mentioned in the comments, this can be achieved with Vuetify 3 using useDisplay().
E.g.
const display = useDisplay();
console.log(display.mobile.value);
I'm working on a project that's both mobile and PC,I need to estimate the mobile terminal or PC terminal。
flexible.js
import { computed } from 'vue'
import { PC_DEVICE_WIDTH } from '../constants'
import { useWindowSize } from '#vueuse/core/index'
const { width } = useWindowSize()
// 判断当前是否为移动设备,判断依据屏幕宽度是否小于一个指定宽度(1280)
export const isMobileTerminal = computed(() => {
return width.value < PC_DEVICE_WIDTH
})
and the navigation/index.vue code is
<template>
<mobile-navigation v-if="isMobileTerminal"></mobile-navigation>
</template>
<script>
import { isMobileTerminal } from '../../../../utils/flexible'
import mobileNavigation from './mobile/index.vue'
export default {
name: 'index',
components: {
mobileNavigation
}
}
</script>
<style lang="scss" scoped></style>
My project catalog is shown below
isMobileTerminal is only imported in your component. It also needs to be made available to the template by declaring it in your component definition.
Returning it from the setup() hook is one way to do that:
<script>
import { isMobileTerminal } from '../../../../utils/flexible'
export default {
setup() {
return {
isMobileTerminal
}
}
}
</script>
Say we want to add a component https://dabernathy89.github.io/vue-query-builder/getting-started.html#usage to the following component. The example they give is not for decorator definitions. Where exactly does the component list go?
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { Store } from 'vuex';
import { readUserProfile } from '#/store/main/getters';
#Component
export default class Loop extends Vue {
get greetedUser() {
const userProfile = readUserProfile(this.$store);
if (userProfile) {
if (userProfile.full_name) {
return userProfile.full_name;
} else {
return userProfile.email;
}
}
}
}
</script>
ugh, I think it is this. Decorators in typescript seem to make the call optional? So the usual component args go inside the decorator call that is implicit if the brackets are not included? I am still just guessing though.
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { Store } from 'vuex';
import { readUserProfile } from '#/store/main/getters';
import VueQueryBuilder from 'vue-query-builder';
#Component({
components: { VueQueryBuilder },
})
export default class Loop extends Vue {
get greetedUser() {
const userProfile = readUserProfile(this.$store);
if (userProfile) {
if (userProfile.full_name) {
return userProfile.full_name;
} else {
return userProfile.email;
}
}
}
}
Why this is undefined here? On logout click this is the error shown in the browser console TypeError: this is undefined
<script lang="ts">
import Vue from "vue";
import { getModule } from "vuex-module-decorators";
import Component from "vue-class-component";
import AuthModule from "#/store/auth";
import Store from "#/store";
const authModule = getModule(AuthModule, Store);
#Component({})
export default class App extends Vue {
mounted() {
console.log("App mounted");
}
onLogoutClick() {
authModule.logout().then(function() {
this.$router.push("/login");
});
}
}
</script>
try this.
methods: {
onLogoutClick() {
let self = this
authModule.logout().then(function() {
self.$router.push("/login");
});
}
Using an arrow function to the anonymous function solves this. As arrow functions bind this to the lexical scope's this (in this case onLogoutClick's this).
onLogoutClick() {
authModule.logout().then(() => {
this.$router.push("/login");
});
}