Ash K
Ash K

Reputation: 3691

Create a global filter in Vue 3 using TypeScript

I'm following this course on Udemy but its content is outdated so I can't follow the same steps that the author has followed to create a global filter.

Also it looks like from Vue 3 documentation, filters are no longer supported.

What I'm trying to do here is fairly simple, it just needs to take a price as a number and return it as string dollar price, for eg: take 100 and return $100.

This doesn't work for me. My main.ts looks like this:

import { createApp } from "vue";
import { Vue } from 'vue-class-component';
import { viewDepthKey } from "vue-router";
import App from "./App.vue";
import router from "./router";
import store from "./store";

Vue.filter('price', function(input: number){
  if(isNaN(input)){
    return "-";
  }
  return '$' + input.toFixed(2);
})

createApp(App)
  .use(store)
  .use(router)
  .mount("#app1");

This is the error:

src/main.ts:8:5
TS2339: Property 'filter' does not exist on type 'VueConstructor<Vue<unknown, {}, {}>>'.
     6 | import store from "./store";
     7 |
  >  8 | Vue.filter('price', function(input: number){
       |     ^^^^^^
     9 |   if(isNaN(input)){
    10 |     return "-";
    11 |   }

This is how I'm trying to use it in the template:

{{ item.product.price | price }}

Is there a way to make it work or should I be using some computed property?

EDIT for a follow up question:

My class looks like this:

<script lang="ts">
import { Options, Vue } from "vue-class-component";
import { IProductInventory } from "@/types/Product";
import format from "@/helpers/format";

@Options({
    name: "Inventory",
    components: {}
})
export default class Inventory extends Vue{
    inventory:IProductInventory[] = //Coming from an api call
}
</script>

Thank you!

Upvotes: 6

Views: 9056

Answers (3)

Jimba Tamang
Jimba Tamang

Reputation: 1335

Using a computed property or methods are ideal solution only if your filters are local. However, if your filters are global and you would like to use in multiple components/pages, it's easy to register a globalProperties instead.

Vue3 migration guide has mentioned this in details.

An example of registering global properties are:

// main.js
const app = createApp(App)

app.config.globalProperties.$filters = {
  currencyUSD(value) {
    return '$' + value
  }
}

Then apply the currentyUSD filters to your template as below:

<template>
  <h1>Bank Account Balance</h1>
  <p>{{ $filters.currencyUSD(accountBalance) }}</p>
</template>

Upvotes: 0

Keith Nicholas
Keith Nicholas

Reputation: 44308

in ./helpers/filters.ts

const filters = {
  price(input: number) {
    if (isNaN(input)) {
      return "-";
    }
    return '$' + input.toFixed(2);
  }
}
export default filters;

install it globally where you create your app...

import filters from './helpers/filters'

const app = createApp(App);
app.config.globalProperties.$filters = filters
app.mount('#app')

then just do

{{ $filters.price( price ) }}

Upvotes: 13

Boussadjra Brahim
Boussadjra Brahim

Reputation: 1

filter option is removed in Vue 3, so you could use a computed property that returns a function with parameter :

    get formatPrice(): string{
        return (price)=>{
             if(isNaN(input)){
               return "-"
             }else{
              //return other value
              }
      }
   }

instead of {{ item.product.price | price }} you'll have :

{{ formatPrice(item.product.price) }}

Upvotes: 2

Related Questions