panthro
panthro

Reputation: 24061

Using a filter inside a v-for?

Inside a v-for loop how can I apply a filter to the text? My inline template:

 <select>
     <option v-for="(item, index) in items" :key="index" :value="item.id" v-text="item.name | capitalize"></option>
</select>

I get multiple warnings Property or method "capitalize" is not defined on the instance but referenced during render. Even though the filter is defined.

So I presume its some sort of scope issue in the loop? How can this be solved?

Upvotes: 0

Views: 340

Answers (1)

Sphinx
Sphinx

Reputation: 10729

As Vue Guide: Filters mentions, Filters are usable in mustache interpolations and v-bind expressions, not including the directives.

For your codes, Solution 1 will be mustache interpolations.

Vue.filter('global-capitalize', function (value) {
  return value.toUpperCase()
})

new Vue({
  el: "#app",
  data: {
    items: [
      { text: "Learn JavaScript", id: 1 },
      { text: "Learn Vue", id: 2 },
      { text: "Play around in JSFiddle", id: 3 },
      { text: "Build something awesome", id: 4 }
    ]
  },
  filters: {
    capitalize: function (name) {
      return name.toUpperCase()
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <h2>Todos:</h2>
  <select>
   <option v-for="(item, index) in items" :key="index" :value="item.id">
   {{item.text | capitalize}}
   </option>
  </select>
  
  <select>
   <option v-for="(item, index) in items" :key="index" :value="item.id">
   {{item.text | global-capitalize}}
   </option>
  </select>
</div>

Another solution is uses computed properties or methods.

new Vue({
  el: "#app",
  data: {
    items: [
      { text: "Learn JavaScript", id: 1 },
      { text: "Learn Vue", id: 2 },
      { text: "Play around in JSFiddle", id: 3 },
      { text: "Build something awesome", id: 4 }
    ]
  },
  computed: {
    computedItems: function () {
      return this.items.map(item => {
        return {text: item.text.toUpperCase(), id: item.id}
      })
    },
  },
  methods: {
    filterFunc: function (name) {
      return name.toUpperCase()
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <select>
   <option v-for="(item, index) in computedItems" :key="index" :value="item.id" v-text="item.text">
   </option>
  </select>
  
  <select>
   <option v-for="(item, index) in items" :key="index" :value="item.id" v-text="filterFunc(item.text)">
   </option>
  </select>
</div>

Upvotes: 1

Related Questions