Cover

Where Did Filters Go in Vue 3?

May 11, 2020
No Comments.

With Vue 3 now in beta, some people are starting to look into it deeper (including me). While a lot of the features are meant to improve the performance and speed, the Vue team did decided to take out a feature lots of people use: filters.

Let’s talk about why filters are gone. Then I’ll show you a pattern I’m using to replicate the functionality.

Where’d They Go?

As a review, in Vue 2 (and 1 actually), Filters were a way to format data in markup. For example:

<div>
  <div>{{ name | uppercase }}</div>
</div>

This syntax was to use a | character to separate the data and the filter to use to represent the data. This worked well but under the covers it was a hack. Vue had to special case this particular syntax so that not all code inside of mustache brackets (e.g. {{ }}) was valid JavaScript.

The decision was made to just remove the functionality so that all bindings could be JavaScript. But then how do you perform formatting in Vue 3?

Replicating the Functionality

Because all bindings are now just JavaScript, you can just use computed or functions to replicate the functionality.

For example, for locally created filters (ones that only apply to the current view), it’s pretty simple to just use a computed property:

<template>
  <div>
    <div>{{ uppercaseName }}</div>
  </div>
</template>
<script>
import { computed, ref } from "vue";

export default {
  setup() { // using the composition API
  
    let name = ref("Shawn");
  
    let uppercaseName = computed(() => { 
      return name.value.toUpperCase();
    });
    
    return {
      name,
      uppercaseName
    }
  }
}
</script>

This works, but it assumes you’re going to wrap anything you need as uppercase with a computed value. Alternatively you could use a function:

<template>
  <div>
    <div>{{ uppercase(name) }}</div>
  </div>
</template>
<script>
import { ref } from "vue";

export default {
  setup() { // using the composition API
  
    let name = ref("Shawn");
  
    function uppercase(val) { 
      return val.toUpperCase();
    };

    return {
      name,
      uppercase
    }
  }
}
</script>

Though for me, it’s a common case to want a shared set of filters for my projects. Since there is no global filter collection, we can do this with just straightforward JavaScript:

// filters.js/ts
export default {
  uppercase(val) {
    if (typeof val === "string") {
      return val.toUpperCase();
    }
    return val;
  }, 
  money(val) {
    if (typeof val === "numeric") {
      return `$${val.toFixed(2)}`;
    }
  }
};

Then we could just include it in our view and use it in the context:

<template>
  <div>
    <div>{{ filters.uppercase(name) }}</div>
  </div>
</template>
<script>
import { ref } from "vue";
import filters from "./filters"
export default {
  setup() { // using the composition API
  
    let name = ref("Shawn");
  
    return {
      name,
      filters
    }
  }
}
</script>

I hope this helps!