Skip to content

Vuex 2.0 module's actions and getters namespacing #335

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jxlarrea opened this issue Sep 25, 2016 · 15 comments
Closed

Vuex 2.0 module's actions and getters namespacing #335

jxlarrea opened this issue Sep 25, 2016 · 15 comments

Comments

@jxlarrea
Copy link

jxlarrea commented Sep 25, 2016

The documentation is quite vague regarding namespacing actions and getters from a module. Can someone please elaborate on how to achieve this?

@jxlarrea jxlarrea changed the title Vuex 2.0 module's actions and getters namspacing Vuex 2.0 module's actions and getters namespacing Sep 25, 2016
@Namek
Copy link

Namek commented Sep 25, 2016

I guess it's something like this:

export const UPDATE_PROPERTY = '*/UPDATE_PROPERTY'

export const CREATE_DAY_DATA = 'day/CREATE_DAY_DATA'
export const LOAD_DAY_DATA = 'day/LOAD_DAY_DATA'

export const FILTER_PRODUCTS = 'products/FILTER_PRODUCTS'
export const SELECT_PRODUCT = 'products/SELECT_PRODUCT'

where / splits between module name and mutation/action type name.

@jxlarrea
Copy link
Author

jxlarrea commented Sep 25, 2016

@Namek honestly that convention doesn't seem too elegant since actions, getters and mutations need to be namespaced. It would be good to have in the documentation some best practices.

@Namek
Copy link

Namek commented Sep 25, 2016

Well, then I don't know what kind of "namespacing" the docs refer to. I got this from some older examples.

@ktsn
Copy link
Member

ktsn commented Sep 26, 2016

Namespacing in the doc means adding prefix or suffix to getters, actions and mutations names to avoid name conflict.

@jxlarrea
Copy link
Author

jxlarrea commented Sep 26, 2016

@ktsn Do you have some sample code with prefixed actions, getters, etc.?

I want to standardize my application's prefixes with something like "module:action", but I have no clue how to make it happen given that I just cant declare an action with a semicolon in the name.

@ktsn
Copy link
Member

ktsn commented Sep 26, 2016

Like this? https://jsfiddle.net/bjahdbx5/1/

@jxlarrea
Copy link
Author

jxlarrea commented Sep 26, 2016

Thank you for the code. That is exactly the result I'm trying to achieve. But it does seem that it would get extremely verbose adding this code to all actions, getters and mutations per module. Is there any way to automate the generation of the prefix in the module.js file?

@ktsn
Copy link
Member

ktsn commented Sep 26, 2016

Do you mean that you do not want to write namespace function each definition?
If so, you can just rewrite the helper function.
https://jsfiddle.net/bjahdbx5/2/

Vuex does not concern about how to define getters, actions and mutations names since it is userland issue.
We should create own helpers as our needs if we suffer to define the constants.

@jxlarrea
Copy link
Author

Thanks for the help @ktsn. Your code helped me to create a helper utility to namespace getters, actions and mutations in Vuex 2.0 modules. This functionality really should be included in Vuex itself. Large application need this, and leaving this for the user to deal with only adds a huge amount of unnecessary boilerplate code.

@ktsn
Copy link
Member

ktsn commented Sep 26, 2016

I think it should not be included into Vuex because it can be solved by external library and using constants is optional.
But anyway, the description of namespace in docs can be improved as you said.
We will consider to add more concrete description and some examples to docs :)

@ktsn
Copy link
Member

ktsn commented Sep 28, 2016

The doc is updated with the description and example about namespace.
http://vuex.vuejs.org/en/modules.html#namespacing

@ktsn ktsn closed this as completed Sep 28, 2016
@jxlarrea
Copy link
Author

Thanks @ktsn. Since namespacing is a must in large size applications, here is how we are doing it with the least amount of boilerplate code:

// namespace.js helper utility

function mapValues (obj, f) {
    const res = {}
    Object.keys(obj).forEach(key => {
        res[key] = f(obj[key], key)
    })
    return res
}

export default (module, types) => {
    let newObj = {};

    mapValues(types, (names, type) => {       
        newObj[type] = {};
        types[type].forEach(name=> {
            var newKey = module + ':' + name;             
            newObj[type][name] = newKey;
        });
    })   
    return newObj;
}

// types.js

import namespace from 'utils/namespace'

export default namespace('auth', {
    getters: [
        'user'
    ],
    actions: [
        'fetchUser'
    ],
    mutations: [
        'receiveUser'     
    ]
})

//module.js

import * as accountApi from 'api/account'
import types from './types'

const state = {
    user: null
}

const actions = {
    [types.actions.fetchUser]: context => {
        return accountApi.me().then(response => {
            context.commit(types.mutations.receiveUser, response)
        });
    }
}

const getters = {
    [types.getters.user]: state => state.user
}

const mutations = {
    [types.mutations.receiveUser]: (state, apiResponse) => {
        state.user = apiResponse.payload;
    }
}

export default {
  state,
  actions,
  getters,
  mutations
};

The above automatically namespaces getters, actions and mutations using the module:action format automatically, without having to manually set the types string constants.

@gyc1299339354
Copy link

Mark~You guys are so cool!

@morficus
Copy link

@jxlarrea - if I understand what you shared correctly, when using your namespace.jsutility function, there would be no need to set namespaced: true in the store its self right?

@patrickdorival
Copy link

@morficus I'm wondering the same thing.
One thing I did notice was that if you change the dynamic key from var newKey = module + ':' + name; using a : to using / then it seems to namespace it by default.

If you leave the module namespacing set to true, then it will double namespace when using the / separator.

I'm still testing it out but I think this is the way to go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants