{"id":15030867,"url":"https://github.com/maoberlehner/vuex-map-fields","last_synced_at":"2025-05-14T19:10:11.280Z","repository":{"id":40813389,"uuid":"115429209","full_name":"maoberlehner/vuex-map-fields","owner":"maoberlehner","description":"Enable two-way data binding for form fields saved in a Vuex store","archived":false,"fork":false,"pushed_at":"2023-10-29T19:35:07.000Z","size":1327,"stargazers_count":1411,"open_issues_count":56,"forks_count":84,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-05-12T01:59:25.207Z","etag":null,"topics":["hacktoberfest"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maoberlehner.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2017-12-26T14:29:55.000Z","updated_at":"2025-04-26T00:23:05.000Z","dependencies_parsed_at":"2024-01-02T23:39:13.311Z","dependency_job_id":"fd2774fc-fb91-476a-870f-c75a397161d8","html_url":"https://github.com/maoberlehner/vuex-map-fields","commit_stats":{"total_commits":107,"total_committers":4,"mean_commits":26.75,"dds":0.09345794392523366,"last_synced_commit":"96fa6b3a70de1f64da251c0ff0caad42e7255944"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maoberlehner%2Fvuex-map-fields","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maoberlehner%2Fvuex-map-fields/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maoberlehner%2Fvuex-map-fields/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maoberlehner%2Fvuex-map-fields/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maoberlehner","download_url":"https://codeload.github.com/maoberlehner/vuex-map-fields/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254209859,"owners_count":22032897,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest"],"created_at":"2024-09-24T20:14:25.560Z","updated_at":"2025-05-14T19:10:10.268Z","avatar_url":"https://github.com/maoberlehner.png","language":"JavaScript","funding_links":["https://www.patreon.com/maoberlehner","https://paypal.me/maoberlehner","https://ko-fi.com/O4O7U55Y"],"categories":["Utilities [🔝](#readme)","JavaScript","公用事业","Components \u0026 Libraries","Utilities"],"sub_categories":["国家管理","Utilities","State Management"],"readme":"# vuex-map-fields\n\n[![Patreon](https://img.shields.io/badge/patreon-donate-blue.svg)](https://www.patreon.com/maoberlehner)\n[![Donate](https://img.shields.io/badge/Donate-PayPal-blue.svg)](https://paypal.me/maoberlehner)\n[![Build Status](https://travis-ci.org/maoberlehner/vuex-map-fields.svg?branch=master)](https://travis-ci.org/maoberlehner/vuex-map-fields)\n[![Coverage Status](https://coveralls.io/repos/github/maoberlehner/vuex-map-fields/badge.svg?branch=master)](https://coveralls.io/github/maoberlehner/vuex-map-fields?branch=master)\n[![GitHub stars](https://img.shields.io/github/stars/maoberlehner/vuex-map-fields.svg?style=social\u0026label=Star)](https://github.com/maoberlehner/vuex-map-fields)\n\n\u003e Enable two-way data binding for form fields saved in a Vuex store.\n\n[![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/O4O7U55Y)\n\n## Install\n\n```bash\nnpm install --save vuex-map-fields\n```\n\n### Basic example\n\nThe following example component shows the most basic usage, for mapping fields to the Vuex store using two-way data binding with `v-model`, without directly modifying the store itself, but using getter and setter functions internally (as it is described in the official Vuex documentation: [Two-way Computed Property](https://vuex.vuejs.org/en/forms.html#two-way-computed-property)).\n\n#### Store\n\n```js\nimport Vue from 'vue';\nimport Vuex from 'vuex';\n\n// Import the `getField` getter and the `updateField`\n// mutation function from the `vuex-map-fields` module.\nimport { getField, updateField } from 'vuex-map-fields';\n\nVue.use(Vuex);\n\nexport default new Vuex.Store({\n  state: {\n    fieldA: '',\n    fieldB: '',\n  },\n  getters: {\n    // Add the `getField` getter to the\n    // `getters` of your Vuex store instance.\n    getField,\n  },\n  mutations: {\n    // Add the `updateField` mutation to the\n    // `mutations` of your Vuex store instance.\n    updateField,\n  },\n});\n```\n\n#### Component\n\n```html\n\u003ctemplate\u003e\n  \u003cdiv id=\"app\"\u003e\n    \u003cinput v-model=\"fieldA\"\u003e\n    \u003cinput v-model=\"fieldB\"\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nimport { mapFields } from 'vuex-map-fields';\n\nexport default {\n  computed: {\n    // The `mapFields` function takes an array of\n    // field names and generates corresponding\n    // computed properties with getter and setter\n    // functions for accessing the Vuex store.\n    ...mapFields([\n      'fieldA',\n      'fieldB',\n    ]),\n  },\n};\n\u003c/script\u003e\n```\n\n[![Edit basic example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/94l98vx0p4)\n\n### Nested properties\n\nOftentimes you want to have nested properties in the Vuex store. `vuex-map-fields` supports nested data structures by utilizing the object dot string notation.\n\n#### Store\n\n```js\nimport Vue from 'vue';\nimport Vuex from 'vuex';\n\nimport { getField, updateField } from 'vuex-map-fields';\n\nVue.use(Vuex);\n\nexport default new Vuex.Store({\n  state: {\n    user: {\n      firstName: '',\n      lastName: '',\n    },\n    addresses: [\n      {\n        town: '',\n      },\n    ],\n  },\n  getters: {\n    getField,\n  },\n  mutations: {\n    updateField,\n  },\n});\n```\n\n#### Component\n\n```html\n\u003ctemplate\u003e\n  \u003cdiv id=\"app\"\u003e\n    \u003cinput v-model=\"firstName\"\u003e\n    \u003cinput v-model=\"lastName\"\u003e\n    \u003cinput v-model=\"town\"\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nimport { mapFields } from 'vuex-map-fields';\n\nexport default {\n  computed: {\n    // When using nested data structures, the string\n    // after the last dot (e.g. `firstName`) is used\n    // for defining the name of the computed property.\n    ...mapFields([\n      'user.firstName',\n      'user.lastName',\n      // It's also possible to access\n      // nested properties in arrays.\n      'addresses[0].town',\n    ]),\n  },\n};\n\u003c/script\u003e\n```\n\n[![Edit nested properties example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/38y88yvoo1)\n\n### Rename properties\n\nSometimes you might want to give your computed properties different names than what you're using in the Vuex store. Renaming properties is made possible by passing an object of fields to the `mapFields` function instead of an array.\n\n```html\n\u003ctemplate\u003e\n  \u003cdiv id=\"app\"\u003e\n    \u003cinput v-model=\"userFirstName\"\u003e\n    \u003cinput v-model=\"userLastName\"\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nimport { mapFields } from 'vuex-map-fields';\n\nexport default {\n  computed: {\n    ...mapFields({\n      userFirstName: 'user.firstName',\n      userLastName: 'user.lastName',\n    }),\n  },\n};\n\u003c/script\u003e\n```\n\n[![Edit rename properties example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/7yowrm6j4x)\n\n### Custom getters and mutations\n\nBy default `vuex-map-fields` is searching for the given properties starting from the root of your state object. Depending on the size of your application, the state object might become quite big and therefore updating the state starting from the root might become a performance issue. To circumvent such problems, it is possible to create a custom `mapFields()` function which is configured to access custom mutation and getter functions which don't start from the root of the state object but are accessing a specific point of the state.\n\n#### Store\n\n```js\nimport Vue from 'vue';\nimport Vuex from 'vuex';\n\nimport { getField, updateField } from 'vuex-map-fields';\n\nVue.use(Vuex);\n\nexport default new Vuex.Store({\n  state: {\n    user: {\n      firstName: '',\n      lastName: '',\n    },\n  },\n  getters: {\n    // By wrapping the `getField()` function we're\n    // able to provide a specific property of the state.\n    getUserField(state) {\n      return getField(state.user);\n    },\n  },\n  mutations: {\n    // Mutating only a specific property of the state\n    // can be significantly faster than mutating the\n    // whole state every time a field is updated.\n    updateUserField(state, field) {\n      updateField(state.user, field);\n    },\n  },\n});\n```\n\n#### Component\n\n```html\n\u003ctemplate\u003e\n  \u003cdiv id=\"app\"\u003e\n    \u003cinput v-model=\"firstName\"\u003e\n    \u003cinput v-model=\"lastName\"\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nimport { createHelpers } from 'vuex-map-fields';\n\n// The getter and mutation types we're providing\n// here, must be the same as the function names we've\n// used in the store.\nconst { mapFields } = createHelpers({\n  getterType: 'getUserField',\n  mutationType: 'updateUserField',\n});\n\nexport default {\n  computed: {\n    // Because we're providing the `state.user` property\n    // to the getter and mutation functions, we must not\n    // use the `user.` prefix when mapping the fields.\n    ...mapFields([\n      'firstName',\n      'lastName',\n    ]),\n  },\n};\n\u003c/script\u003e\n```\n\n[![Edit custom getters and mutations example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/4rroy51z8x)\n\n### Vuex modules\n\nVuex makes it possible to divide the store into modules.\n\n#### Store\n\n```js\nimport Vue from 'vue';\nimport Vuex from 'vuex';\n\nimport { createHelpers } from 'vuex-map-fields';\n\n// Because by default, getters and mutations in Vuex\n// modules, are globally accessible and not namespaced,\n// you most likely want to rename the getter and mutation\n// helpers because otherwise you can't reuse them in multiple,\n// non namespaced modules.\nconst { getFooField, updateFooField } = createHelpers({\n  getterType: 'getFooField',\n  mutationType: 'updateFooField',\n});\n\nVue.use(Vuex);\n\nexport default new Vuex.Store({\n  // ...\n  modules: {\n    fooModule: {\n      state: {\n        foo: '',\n      },\n      getters: {\n        getFooField,\n      },\n      mutations: {\n        updateFooField,\n      },\n    },\n  },\n});\n```\n\n#### Component\n\n```html\n\u003ctemplate\u003e\n  \u003cdiv id=\"app\"\u003e\n    \u003cinput v-model=\"foo\"\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nimport { createHelpers } from 'vuex-map-fields';\n\n// We're using the same getter and mutation types\n// as we've used in the store above.\nconst { mapFields } = createHelpers({\n  getterType: 'getFooField',\n  mutationType: 'updateFooField',\n});\n\nexport default {\n  computed: {\n    ...mapFields(['foo']),\n  },\n};\n\u003c/script\u003e\n```\n\n[![Edit Vuex modules example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/mo7j05j6vy)\n\n### Namespaced Vuex modules\n\nBy default, mutations and getters inside modules are registered under the global namespace – but you can mark modules as `namespaced` which prevents naming clashes of mutations and getters between modules.\n\n#### Store\n\n```js\nimport Vue from 'vue';\nimport Vuex from 'vuex';\n\nimport { getField, updateField } from 'vuex-map-fields';\n\nVue.use(Vuex);\n\nexport default new Vuex.Store({\n  // ...\n  modules: {\n    fooModule: {\n      namespaced: true,\n      state: {\n        foo: '',\n      },\n      getters: {\n        getField,\n      },\n      mutations: {\n        updateField,\n      },\n    },\n  },\n});\n```\n\n#### Component\n\n```html\n\u003ctemplate\u003e\n  \u003cdiv id=\"app\"\u003e\n    \u003cinput v-model=\"foo\"\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nimport { createHelpers } from 'vuex-map-fields';\n\n// `fooModule` is the name of the Vuex module.\nconst { mapFields } = createHelpers({\n  getterType: 'fooModule/getField',\n  mutationType: 'fooModule/updateField',\n});\n\nexport default {\n  computed: {\n    ...mapFields(['foo']),\n  },\n};\n\u003c/script\u003e\n```\n\n[![Edit namespaced Vuex modules example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/mly87n06p)\n\nOr you can pass the module namespace string as the first argument of the `mapFields()` function.\n\n```html\n\u003ctemplate\u003e\n  \u003cdiv id=\"app\"\u003e\n    \u003cinput v-model=\"foo\"\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nimport { mapFields } from 'vuex-map-fields';\n\nexport default {\n  computed: {\n    // `fooModule` is the name of the Vuex module.\n    ...mapFields('fooModule', ['foo']),\n  },\n};\n\u003c/script\u003e\n```\n\n[![Edit namespaced Vuex modules example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/m51j02794p)\n\n### Multi-row fields\n\nIf you want to build a form which allows the user to enter multiple rows of a specific data type with multiple fields (e.g. multiple addresses) you can use the multi-row field mapping function.\n\n#### Store\n\n```js\nimport Vue from 'vue';\nimport Vuex from 'vuex';\n\nimport { getField, updateField } from 'vuex-map-fields';\n\nVue.use(Vuex);\n\nexport default new Vuex.Store({\n  // ...\n  state: {\n    addresses: [\n      {\n        zip: '12345',\n        town: 'Foo Town',\n      },\n      {\n        zip: '54321',\n        town: 'Bar Town',\n      },\n    ],\n  },\n  getters: {\n    getField,\n  },\n  mutations: {\n    updateField,\n  },\n});\n```\n\n#### Component\n\n```html\n\u003ctemplate\u003e\n  \u003cdiv id=\"app\"\u003e\n    \u003cdiv v-for=\"address in addresses\"\u003e\n      \u003clabel\u003eZIP \u003cinput v-model=\"address.zip\"\u003e\u003c/label\u003e\n      \u003clabel\u003eTown \u003cinput v-model=\"address.town\"\u003e\u003c/label\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nimport { mapMultiRowFields } from 'vuex-map-fields';\n\nexport default {\n  computed: {\n    ...mapMultiRowFields(['addresses']),\n  },\n};\n\u003c/script\u003e\n```\n\n[![Edit multi-row fields example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/yj1xxx8kn1)\n\n## Upgrade from 0.x.x to 1.x.x\n\nInstead of accessing the state directly, since the 1.0.0 release, in order to enable the ability to implement custom getters and mutations, `vuex-map-fields` is using a getter function to access the state. This makes it necessary to add a getter function to your Vuex store.\n\n```js\nimport Vue from 'vue';\nimport Vuex from 'vuex';\n\n// You now have to also import the `getField()` function.\nimport { getField, updateField } from 'vuex-map-fields';\n\nVue.use(Vuex);\n\nexport default new Vuex.Store({\n  state: {\n    fieldA: '',\n    fieldB: '',\n  },\n  getters: {\n    // Add the `getField` getter to the\n    // `getters` of your Vuex store instance.\n    getField,\n  },\n  mutations: {\n    updateField,\n  },\n});\n```\n\n## Patreon Sponsors\n\n[![Spiffy](https://res.cloudinary.com/maoberlehner/image/upload/c_scale,h_68,q_auto/v1549339992/github/vuex-map-fields/spiffy-logo.png)](https://spiffy.co/)\n\n[Become a sponsor](https://www.patreon.com/maoberlehner) and get your logo in this README with a link to your site.\n\n## Articles\n\n- [Form Fields, Two-Way Data Binding and Vuex](https://markus.oberlehner.net/blog/form-fields-two-way-data-binding-and-vuex/)\n- [How to Handle Multi-row Forms with Vue, Vuex and vuex-map-fields](https://markus.oberlehner.net/blog/how-to-handle-multi-row-forms-with-vue-vuex-and-vuex-map-fields/)\n- [How to Structure a Complex Vuex Store](https://markus.oberlehner.net/blog/how-to-structure-a-complex-vuex-store/)\n\n## About\n\n### Author\n\nMarkus Oberlehner  \nWebsite: https://markus.oberlehner.net  \nTwitter: https://twitter.com/MaOberlehner  \nPayPal.me: https://paypal.me/maoberlehner  \nPatreon: https://www.patreon.com/maoberlehner\n\n### License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaoberlehner%2Fvuex-map-fields","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaoberlehner%2Fvuex-map-fields","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaoberlehner%2Fvuex-map-fields/lists"}