Module

Creating empty module

Let's create an empty Vuex module for our todo app. Create a file todo.js in the folder Application\src\store\modules\ and put such initial content to it:

import api from '../../utils/api';
import router from '../../router';

// initial state
const state = {
    errors: {}
};

// mutations
const mutations = {
	errors(state, errors) {
        state.errors = errors;
    },
};

// actions
const actions = {
    back() {
        router.push({
            name: 'dashboard'
        });
    }
};

export default {
    namespaced: true,
    state,
    actions,
    mutations
};

And now we should add this module to the list of vuex modules. Open the file Application\src\store\index.js and add these lines:




 



















 



...
import table from './modules/table';
import catalog from './modules/catalog';
import todo from './modules/todo';

Vue.use(Vuex);

export default new Vuex.Store({
    modules: {
        dateTimePicker,
        confirmation,
        settings,
        translation,
        signin,
        signup,
        forgotPassword,
        dashboard,
        configuration,
        list,
        listItem,
        form,
        table,
        catalog,
        todo
    }
});

Getting all items

Add new variable to the state for storing items:






 





...

// initial state
const state = {
      errors: {},
	  items: []
};

...

Then create a mutation for updating items variable:






 
 
 





...

// mutations
const mutations = {
    ...
    items(state, items) {
        state.items = items;
    }
};

...

Finally add an action that will retrieve all items via api and store it:





 
 
 
 
 





...

// actions
const actions = {
    getItems(store) {
        api.get('/api/todo/').then(function(response) {
            store.commit('items', response.body);
        });
    }
};

...

Title of new item

We will need to store and update the title before we will use it for creating the item. Add new variable to the state for storing the title:







 





...

// initial state
const state = {
    errors: {},
	items: [],
    title: ''
};

...

Then create a mutation for updating the title:






 
 
 





...

// mutations
const mutations = {
    ...
    title(state, value) {
        state.title = value;
    }
};

...

Finally add an action that will set the title:






 
 
 





...

// actions
const actions = {
    ...
    setTitle(store, value) {
        store.commit('title', value);
    }
};

...

Creating new item

Now we can write methods for creating new item. Add mutation for adding new item to the end of the list:




 
 
 



// mutations
const mutations = {
    ...
    addItem(state, item) {
        state.items.push(item);
    },
    ...
};

Great! Now add an action for creating an item by title using api:

// actions
const actions = {
    ...
    createItem(store) {
        api.post('/api/todo/',
            {
                id: null,
                title: store.state.title,
                done: false
            },
            'todo/errors').then(function (response) {
                store.commit('addItem', response.body);
                store.commit('title', '');
            });
    },
    ...
};

Marking item as done

To make an item completed add a mutation:



 
 
 



const mutations = {
    ...
    done(state, index) {
        state.items[index].done = true;
    },
    ...
};

And now we can add an action for updating item:

// actions
const actions = {
    ...
    markAsDone(store, index) {
        store.commit('done', index);
        const item = store.state.items[index];
        api.put(`/api/todo/${item.id}`,
            {
                id: item.id,
                title: item.title,
                done: true
            })
            .then(
                function (response) {
                },
                function (response) {
                    //Reload items on error
                    store.dispatch('getItems');
                });
    },
    ...
};

Remove completed items

Finally we want to have ability to remove all completed items with a single click. So let's create a mutation for it:

const mutations = {
    ...
    removeCompleted(state) {
        for (let i = state.items.length - 1; i >= 0; i--) {
            if (state.items[i].done) {
                state.items.splice(i, 1);
            }
        }
    },
    ...
};

Then create an action:

// actions
const actions = {
    ...
     removeCompleted(store) {
        const ids = [];
        for (let i = 0; i < store.state.items.length; i++) {
            if (store.state.items[i].done) {
                ids.push(store.state.items[i].id);
            }
        }

        store.commit('removeCompleted');

        for (let i = 0; i < ids.length; i++) {
            api.delete(`/api/todo/${ids[i]}`)
                .then(
                    function (response) {
                    },
                    function (response) {
                        //Reload items on error
                        store.dispatch('getItems');
                    });
        }
    },
    ...
};

Complete module sources

import api from '../../utils/api';
import router from '../../router';

// initial state
const state = {
    errors: {},
    items: [],
    title: ''
};

// mutations
const mutations = {
    errors(state, errors) {
        state.errors = errors;
    },
    items(state, items) {
        state.items = items;
    },
    addItem(state, item) {
        state.items.push(item);
    },
    done(state, index) {
        state.items[index].done = true;
    },
    removeCompleted(state) {
        for (let i = state.items.length - 1; i >= 0; i--) {
            if (state.items[i].done) {
                state.items.splice(i, 1);
            }
        }
    },
    title(state, value) {
        state.title = value;
    }
};

// actions
const actions = {
    getItems(store) {
        api.get('/api/todo/').then(function (response) {
            store.commit('items', response.body);
        });
    },
    createItem(store, title) {
        api.post('/api/todo/',
            {
                id: null,
                title: title,
                done: false
            },
            'todo/errors').then(function (response) {
                store.commit('addItem', response.body);
                store.commit('title', '');
            });
    },
    markAsDone(store, index) {
        store.commit('done', index);
        const item = store.state.items[index];
        api.put(`/api/todo/${item.id}`,
            {
                id: item.id,
                title: item.title,
                done: true
            })
            .then(
                function (response) {
                },
                function (response) {
                    //Reload items on error
                    store.dispatch('getItems');
                });
    },
    removeCompleted(store) {
        const ids = [];
        for (let i = 0; i < store.state.items.length; i++) {
            if (store.state.items[i].done) {
                ids.push(store.state.items[i].id);
            }
        }

        store.commit('removeCompleted');

        for (let i = 0; i < ids.length; i++) {
            api.delete(`/api/todo/${ids[i]}`)
                .then(
                    function (response) {
                    },
                    function (response) {
                        //Reload items on error
                        store.dispatch('getItems');
                    });
        }
    },
    setTitle(store, value) {
        store.commit('title', value);
    },
	back() {
        router.push({
            name: 'dashboard'
        });
    }
};

export default {
    namespaced: true,
    state,
    actions,
    mutations
};