3

I'm using a template to get data of a json file, I use "v-for" to print all data, for example:

template: /*html*/
    ` 
    <div class="col-lg-8">
        <template v-for="item of actividades">
            <ul>
                <li>{{ item.date }}</li>
            <ul>
        </template>
    </div>
    `,

But I need use functions, year() to modificate this information and return and result, for example:

   template: /*html*/
    ` 
    <div class="col-lg-8">
        <template v-for="item of actividades">
            <ul>
                <li>{{ year(item.date) }}</li>
            <ul>
        </template>
    </div>
    `,

The value {{ item.date }} print "2021-01-20" but I hope print "2021" using the function {{ year(item.date) }}

Code function year() using javascript:

year(date){
            return String(date).substr(0, 4);
        }

I tried use that code but is not working, appear this error: this image show error

That's my javascript code:

//VueEx
const store = new Vuex.Store({
    state: {
        actividades: [],
        programas: [],
        year: ""
    },
    mutations: {
        llamarJsonMutation(state, llamarJsonAction){
            state.actividades = llamarJsonAction.Nueva_estructura_proveedor;
            state.programas = llamarJsonAction.BD_programas;
        },
        yearFunction(state, date){
            state.year = String(date).substr(8, 2);
            return state.year;
        }
    },
    actions: {
        llamarJson: async function({ commit }){
            const data = await fetch('calendario-2021-prueba.json');
            const dataJson = await data.json();
            commit('llamarJsonMutation', dataJson);
        }
    }
});

//Vue
new Vue({
    el: '#caja-vue',
    store: store,
    created() {
        this.$store.dispatch('llamarJson');
      }
});
6
  • How is it not "working"? What's the expected outcome? What actually happened? Commented Dec 19, 2020 at 19:14
  • Appear loop error. Commented Dec 19, 2020 at 19:22
  • What's the error message? Commented Dec 19, 2020 at 19:36
  • Your first part of the question of about a component which is looping data and needs a year function, your second part of about a vuex store, but you don't show how these two interact. Really hard to understand your problem. Commented Dec 19, 2020 at 21:47
  • 1
    I'm not sure it's allow to use a function in {{}}. Anyway I think you could deal with the data in function llamarJsonMutation before where it assigned to actividades. Commented Dec 20, 2020 at 3:04

2 Answers 2

4

Inside a template you can use functions defined as methods or computed. Technically, you can also use data to pass a function to the template, but I wouldn't recommend it. Not that it wouldn't work, but Vue makes anything declared in data reactive and there's no point in making a function (which is basically a constant) reactive. So, in your case:

new Vue({
  el: '#app',
  data: () => ({
    actividades: [
      { date: '2021-01-20' },
      { date: '2020-01-20' },
      { date: '2019-01-20' },
      { date: '2018-01-20' },
      { date: '2017-01-20' }
    ]
  }),
  methods: {
    year(date) { return date.substring(0, 4); }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <ul>
      <li v-for="(item, key) in actividades" :key="key">
        {{ year(item.date) }}
      </li>
  </ul>
</div>

If, for some reason, you want to pass year as computed:

computed: {
  year() { return date => date.substring(0, 4); }
}

But it's a convoluted construct (a getter function returning an inner arrow function) and this complexity doesn't serve any purpose. I'd recommend you use a method in your case, since it's the most straight-forward (easy to read/understand).


If you're importing the year function from another file:

import { year } from '../helpers'; // random example, replace with your import

// inside component's methods:

methods: {
  year, // this provides `year` imported function to the template, as `year`
        // it is equivalent to `year: year,`
  // other methods here
}

Side notes:

  • there is no point in iterating through <template> tags which contain <ul>'s. You can place the v-for directly on the <ul> and lose the <template> (You should only use <template> when you want to apply some logic - i.e: a v-if - to a bunch of elements without actually wrapping them into a DOM wrapper; another use-case is when you want its children to be direct descendants of the its parent: for <ul>/<li> or <tbody>/<tr> relations, where you can't have intermediary wrappers between them). In your case, placing the v-for on the <ul> produces the exact same result with less code.
  • you should always key your v-for's: <ul v-for="(item, key) in actividades" :key="key">. Keys help Vue maintain the state of list elements, keep track of animations and update them correctly
Sign up to request clarification or add additional context in comments.

1 Comment

your explication is awesome, thank you so much.
0

I see you are trying to work with the Vuex store. And using mutation inside the template syntax.

Not sure if we can call mutation directly via HTML as the way you are doing. In the past when I tried to call a mutation, I would either:

Vue.component('followers', {
  template: '<div>Followers: {{ computedFollowers }} {{printSampleLog()}}</div>',
  data() {
    return { followers: 0 }
  },
  created () {
    this.$store.dispatch('getFollowers').then(res => {
        this.followers = res.data.followers
    })
  },
  computed: {
    computedFollowers: function () {
        return this.followers
    }
  },
  methods:{
  printSampleLog(){
  this.$store.dispatch('sampleAction').then(res => {
        this.followers = res.data.followers
    })
  }
  }
});

const store = new Vuex.Store({
  actions: {
    getFollowers() {
      return new Promise((resolve, reject) => {
        axios.get('https://api.github.com/users/octocat')
          .then(response => resolve(response))
          .catch(err => reject(error))
      });
    },
    sampleAction(context){
    context.commit('sampleMutation');
    }
  },
  mutations: {
  sampleMutation(){
    console.log("sample mutation")
  }
  }
})

const app = new Vue({
    store,
  el: '#app'
})
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<div id="app">
  <followers></followers>
</div>

  • Else create method w/o action in your Vue component committing the mutation directly, using this.$store.commit()

PS: Would recommend creating action around the mutation first, as it is a much cleaner approach.

2 Comments

@luis, let me know if I understood your question correctly.
It's perfectly safe to call mutations or actions from anywhere. The only difference is that actions are async (and return a promise - they have a .then()) and mutations are synchronous.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.