djcaesar9114
djcaesar9114

Reputation: 2137

Using momentJS globally in VueJS 3

In VueJS 2, I could use momentJS globally like this:

in main.js:

import moment from 'moment';
moment.locale('fr');
Object.defineProperty(Vue.prototype, '$moment', { value: moment });

in any component:

{{ item.date_creation?$moment(item.date_creation).format('l'):'No date'}}

In VueJS 3 I tried to do the following in main.js:

import { createApp } from 'vue';
import moment from 'moment';
import App from './App.vue';
import './registerServiceWorker';
import router from './router';
import store from './store';

moment.locale('fr');

createApp(App).use(moment).use(store).use(router)
  .mount('#app');

But actually I can't use "moment" in any of my component, I have to import "moment" in each of them. Isn't there a better solution? I read a lot of documentation and tutorials, I didn't see anything good... Thanks in advance.

Edit: here is how I use $moment in my component:

<template>
  <div class="xx" :key="'title-'+myReactiveVariable.title">
    <h1>{{ myReactiveVariable.title }}</h1>
    <div class="yy">
      {{ myReactiveVariable.content }}
    </div>
    <footer>
      Sent on
      {{ myReactiveVariable.date }}
      by {{ myReactiveVariable.author }}
      <who-is-it :idSent="id" :key="'ID-'+id">
      </who-is-it>
    </footer>
  </div>
</template>

<script>
// @ is an alias to /src
import WhoIsIt from '@/components/WhoIsIt.vue';

import {
  defineComponent, reactive, onMounted, watch, ref,
} from 'vue';

import axios from 'axios';

import { useRoute } from 'vue-router';

export default defineComponent({
  name: 'XXX',
  components: {
    WhoIsIt,
  },
  setup() {
    const route = useRoute();

    const myReactiveVariable = reactive({
      title: '',
      content: '',
      date: '',
    });

    const id = ref('');

    async function fetchArticle(id) {
      console.log(`A: ${process.env.VUE_APP_API_URL} - ${id}`);
      const res = await axios.get(`${process.env.VUE_APP_API_URL}/whoarewe/${id}`);
      id.value = res.data.author;
      myReactiveVariable.titre = res.data.title;
      myReactiveVariable.content = res.data.content;
      myReactiveVariable.date = this.$moment(res.data.date).format('l');
    }

    watch(() => route.params.id, () => {
      fetchArticle(route.params.id);
    });

    onMounted(async () => {
      fetchArticle(route.params.id);
    });

    return {
      myReactiveVariable,
      id,
    };
  },
});
</script>

Upvotes: 3

Views: 11578

Answers (2)

Whitespacecode
Whitespacecode

Reputation: 1378

With Vue 3.x, you can use provide() and inject() to pipe global values into any component without prop drilling.

The problem with app.config.globalProperties is that you can't use them with Vue 3.x composition api.

Prior to mounting your app, import moment and provide it to your app. This must be done before you mount your app

//app.js
import moment from "moment";

const app = createApp(App);
app.provide("moment", moment);

Inject in any Vue file (You can use moment in the setup or in your template)

//component.vue
<script>
import { inject } from 'vue';

export default {
    setup() {
      const moment = inject('moment');

      return { moment };
    },
};
</script>

<template>
  <time :datetime="item.created_at">
     {{ moment(item.created_at).format('LL - HH:MM') }}
  </time>
</template>

Upvotes: 1

Boussadjra Brahim
Boussadjra Brahim

Reputation: 1

Add the moment to the global config properties app.config.globalProperties.$moment=moment:

import { createApp } from 'vue';
import moment from 'moment';
import App from './App.vue';
import './registerServiceWorker';
import router from './router';
import store from './store';

moment.locale('fr');

let app=createApp(App);

app.config.globalProperties.$moment=moment;

app.use(store).use(router)
  .mount('#app');

then use this.$moment in any child component with option api, with composition you should use getCurrentInstance :

import { getCurrentInstance } from 'vue'

setup(){
  const internalInstance = getCurrentInstance()
  ...
  myReactiveVariable.date = internalInstance.appContext.config.globalProperties.$moment(res.data.date).format('l');

}

You couldn't do app.use(moment) since moment is not a Vue plugin.

Upvotes: 9

Related Questions